DHCP: implement simple Server/Client (solicit/reply) (#884)

* DHCP implementation
- implementation Dhcp client/server (solicit/reply)
- two build options --enable-dhcp6-server  --enable-dhcp6-client (default disable)
- add Cert_5_3_09_AddressQuery for Dhcp Client/Server test in travis
This commit is contained in:
rongli
2016-10-31 21:38:56 -07:00
committed by Jonathan Hui
parent 196c28d022
commit 3001fc689c
36 changed files with 2844 additions and 33 deletions
+2 -2
View File
@@ -49,14 +49,14 @@ set -x
[ $BUILD_TARGET != arm-gcc49 ] || {
export PATH=/tmp/gcc-arm-none-eabi-4_9-2015q3/bin:$PATH || die
COMMISSIONER=1 JOINER=1 make -f examples/Makefile-cc2538 || die
COMMISSIONER=1 JOINER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 make -f examples/Makefile-cc2538 || die
arm-none-eabi-size output/bin/arm-none-eabi-ot-cli || die
arm-none-eabi-size output/bin/arm-none-eabi-ot-ncp || die
}
[ $BUILD_TARGET != arm-gcc54 ] || {
export PATH=/tmp/gcc-arm-none-eabi-5_4-2016q3/bin:$PATH || die
COMMISSIONER=1 JOINER=1 make -f examples/Makefile-cc2538 || die
COMMISSIONER=1 JOINER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 make -f examples/Makefile-cc2538 || die
arm-none-eabi-size output/bin/arm-none-eabi-ot-cli || die
arm-none-eabi-size output/bin/arm-none-eabi-ot-ncp || die
}
+2
View File
@@ -37,6 +37,8 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \
--with-examples=posix \
--enable-commissioner \
--enable-joiner \
--enable-dhcp6-client \
--enable-dhcp6-server \
$(NULL)
SUBDIRS = \
+69 -6
View File
@@ -383,7 +383,7 @@ fi
#
AC_ARG_ENABLE(cli,
[AS_HELP_STRING([--enable-cli],[Enable CLI suport @<:@default=no@:>@.])],
[AS_HELP_STRING([--enable-cli],[Enable CLI support @<:@default=no@:>@.])],
[
case "${enableval}" in
@@ -405,7 +405,7 @@ AM_CONDITIONAL([OPENTHREAD_ENABLE_CLI], [test "${enable_cli}" = "yes"])
#
AC_ARG_ENABLE(ncp,
[AS_HELP_STRING([--enable-ncp[[=spi|uart]]],[Enable NCP suport @<:@default=no@:>@.])],
[AS_HELP_STRING([--enable-ncp[[=spi|uart]]],[Enable NCP support @<:@default=no@:>@.])],
[
case "${enableval}" in
@@ -462,7 +462,7 @@ AM_CONDITIONAL([OPENTHREAD_ENABLE_BUILTIN_MBEDTLS], [test "${enable_builtin_mbed
#
AC_ARG_ENABLE(commissioner,
[AS_HELP_STRING([--enable-commissioner],[Enable commissioner suport @<:@default=no@:>@.])],
[AS_HELP_STRING([--enable-commissioner],[Enable commissioner support @<:@default=no@:>@.])],
[
case "${enableval}" in
@@ -493,7 +493,7 @@ AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_COMMISSIONER],[${OPENTHREAD_ENABLE_COMMISS
#
AC_ARG_ENABLE(joiner,
[AS_HELP_STRING([--enable-joiner],[Enable joiner suport @<:@default=no@:>@.])],
[AS_HELP_STRING([--enable-joiner],[Enable joiner support @<:@default=no@:>@.])],
[
case "${enableval}" in
@@ -537,7 +537,7 @@ AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_DTLS],[${OPENTHREAD_ENABLE_DTLS}],[Define
#
AC_ARG_ENABLE(diag,
[AS_HELP_STRING([--enable-diag],[Enable diagnostics suport @<:@default=no@:>@.])],
[AS_HELP_STRING([--enable-diag],[Enable diagnostics support @<:@default=no@:>@.])],
[
case "${enableval}" in
@@ -568,7 +568,7 @@ AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_DIAG],[${OPENTHREAD_ENABLE_DIAG}],[Define
#
AC_ARG_ENABLE(cli_logging,
[AS_HELP_STRING([--enable-cli-logging],[Enable cli logging suport @<:@default=no@:>@.])],
[AS_HELP_STRING([--enable-cli-logging],[Enable cli logging support @<:@default=no@:>@.])],
[
case "${enableval}" in
@@ -623,6 +623,66 @@ AC_SUBST(OPENTHREAD_ENABLE_CERT_LOG)
AM_CONDITIONAL([OPENTHREAD_ENABLE_CERT_LOG], [test "${enable_cert_log}" = "yes"])
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_CERT_LOG],[${OPENTHREAD_ENABLE_CERT_LOG}],[Define to 1 if you want to enable log for certification test])
#
# DHCPv6 Client
#
AC_ARG_ENABLE(dhcp6_client,
[AS_HELP_STRING([--enable-dhcp6-client],[Enable DHCPv6 client support @<:@default=no@:>@.])],
[
case "${enableval}" in
no|yes)
enable_dhcp6_client=${enableval}
;;
*)
AC_MSG_ERROR([Invalid value ${enable_dhcp6_client} for --enable-dhcp6-client])
;;
esac
],
[enable_dhcp6_client=no])
if test "$enable_dhcp6_client" = "yes"; then
OPENTHREAD_ENABLE_DHCP6_CLIENT=1
else
OPENTHREAD_ENABLE_DHCP6_CLIENT=0
fi
AC_SUBST(OPENTHREAD_ENABLE_DHCP6_CLIENT)
AM_CONDITIONAL([OPENTHREAD_ENABLE_DHCP6_CLIENT], [test "${enable_dhcp6_client}" = "yes"])
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_DHCP6_CLIENT],[${OPENTHREAD_ENABLE_DHCP6_CLIENT}],[Define to 1 if you want to enable DHCPv6 Client])
#
# DHCPv6 Server
#
AC_ARG_ENABLE(dhcp6_server,
[AS_HELP_STRING([--enable-dhcp6-server],[Enable DHCPv6 server support @<:@default=no@:>@.])],
[
case "${enableval}" in
no|yes)
enable_dhcp6_server=${enableval}
;;
*)
AC_MSG_ERROR([Invalid value ${enable_dhcp6_server} for --enable-dhcp6-server])
;;
esac
],
[enable_dhcp6_server=no])
if test "$enable_dhcp6_server" = "yes"; then
OPENTHREAD_ENABLE_DHCP6_SERVER=1
else
OPENTHREAD_ENABLE_DHCP6_SERVER=0
fi
AC_SUBST(OPENTHREAD_ENABLE_DHCP6_SERVER)
AM_CONDITIONAL([OPENTHREAD_ENABLE_DHCP6_SERVER], [test "${enable_dhcp6_server}" = "yes"])
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_DHCP6_SERVER],[${OPENTHREAD_ENABLE_DHCP6_SERVER}],[Define to 1 if you want to enable DHCPv6 Server])
#
# Examples
#
@@ -789,6 +849,7 @@ Makefile
include/Makefile
include/cli/Makefile
include/commissioning/Makefile
include/dhcp6/Makefile
include/ncp/Makefile
include/platform/Makefile
src/Makefile
@@ -880,6 +941,8 @@ AC_MSG_NOTICE([
OpenThread Diagnostics support : ${enable_diag}
OpenThread Cli logging support : ${enable_cli_logging}
OpenThread Certification log support : ${enable_cert_log}
OpenThread DHCPv6 Server support : ${enable_dhcp6_server}
OpenThread DHCPv6 Client support : ${enable_dhcp6_client}
OpenThread examples : ${OPENTHREAD_EXAMPLES}
OpenThread platform information : ${PLATFORM_INFO}
+7 -2
View File
@@ -45,6 +45,8 @@
<ClCompile Include="..\..\src\core\meshcop\joiner_router.cpp" />
<ClCompile Include="..\..\src\core\meshcop\leader.cpp" />
<ClCompile Include="..\..\src\core\meshcop\panid_query_client.cpp" />
<ClCompile Include="..\..\src\core\net\dhcp6_client.cpp" />
<ClCompile Include="..\..\src\core\net\dhcp6_server.cpp" />
<ClCompile Include="..\..\src\core\net\icmp6.cpp" />
<ClCompile Include="..\..\src\core\net\ip6.cpp" />
<ClCompile Include="..\..\src\core\net\ip6_address.cpp" />
@@ -75,7 +77,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" />
<ClCompile Include="..\..\src\core\utils\slaac_address.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\core\coap\coap_client.hpp" />
@@ -122,6 +124,9 @@
<ClInclude Include="..\..\src\core\thread\address_resolver.hpp" />
<ClInclude Include="..\..\src\core\meshcop\announce_begin_server.hpp" />
<ClInclude Include="..\..\src\core\thread\energy_scan_server.hpp" />
<ClInclude Include="..\..\src\core\net\dhcp6.hpp" />
<ClInclude Include="..\..\src\core\net\dhcp6_client.hpp" />
<ClInclude Include="..\..\src\core\net\dhcp6_server.hpp" />
<ClInclude Include="..\..\src\core\thread\key_manager.hpp" />
<ClInclude Include="..\..\src\core\thread\link_quality.hpp" />
<ClInclude Include="..\..\src\core\thread\lowpan.hpp" />
@@ -144,7 +149,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" />
<ClInclude Include="..\..\src\core\utils\slaac_address.hpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{DD5018BE-54C6-4FD4-9F8D-08D52FC0CD40}</ProjectGuid>
@@ -93,6 +93,12 @@
<ClCompile Include="..\..\src\core\mac\mac_whitelist.cpp">
<Filter>Source Files\mac</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\net\dhcp6_client.cpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\net\dhcp6_server.cpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\net\icmp6.cpp">
<Filter>Source Files\net</Filter>
</ClCompile>
@@ -216,7 +222,7 @@
<ClCompile Include="..\..\src\core\crypto\sha256.cpp">
<Filter>Source Files\crypto</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\utils\global_address.cpp">
<ClCompile Include="..\..\src\core\utils\slaac_address.cpp">
<Filter>Source Files\utils</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\meshcop\announce_begin_client.cpp">
@@ -284,6 +290,15 @@
<ClInclude Include="..\..\src\core\mac\mac_whitelist.hpp">
<Filter>Header Files\mac</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\net\dhcp6.hpp">
<Filter>Header Files\net</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\net\dhcp6_client.hpp">
<Filter>Header Files\net</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\net\dhcp6_server.hpp">
<Filter>Header Files\net</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\net\icmp6.hpp">
<Filter>Header Files\net</Filter>
</ClInclude>
@@ -419,7 +434,7 @@
<ClInclude Include="..\..\src\core\crypto\sha256.hpp">
<Filter>Header Files\crypto</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\utils\global_address.hpp">
<ClInclude Include="..\..\src\core\utils\slaac_address.hpp">
<Filter>Header Files\utils</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\meshcop\announce_begin_client.hpp">
+9 -3
View File
@@ -106,6 +106,9 @@
<ClCompile Include="..\..\src\core\meshcop\joiner_router.cpp" />
<ClCompile Include="..\..\src\core\meshcop\leader.cpp" />
<ClCompile Include="..\..\src\core\meshcop\panid_query_client.cpp" />
<ClInclude Include="..\..\src\core\net\dhcp6.cpp" />
<ClInclude Include="..\..\src\core\net\dhcp6_client.cpp" />
<ClInclude Include="..\..\src\core\net\dhcp6_server.cpp" />
<ClCompile Include="..\..\src\core\net\icmp6.cpp" />
<ClCompile Include="..\..\src\core\net\ip6.cpp" />
<ClCompile Include="..\..\src\core\net\ip6_address.cpp" />
@@ -136,7 +139,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" />
<ClCompile Include="..\..\src\core\utils\slaac_address.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\openthread.h" />
@@ -172,6 +175,9 @@
<ClInclude Include="..\..\src\core\meshcop\joiner_router.hpp" />
<ClInclude Include="..\..\src\core\meshcop\leader.hpp" />
<ClInclude Include="..\..\src\core\meshcop\panid_query_client.hpp" />
<ClInclude Include="..\..\src\core\net\dhcp6.hpp" />
<ClInclude Include="..\..\src\core\net\dhcp6_client.hpp" />
<ClInclude Include="..\..\src\core\net\dhcp6_server.hpp" />
<ClInclude Include="..\..\src\core\net\icmp6.hpp" />
<ClInclude Include="..\..\src\core\net\ip6.hpp" />
<ClInclude Include="..\..\src\core\net\ip6_address.hpp" />
@@ -210,8 +216,8 @@
<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" />
<ClInclude Include="..\..\src\core\utils\slaac_address.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
</Project>
@@ -93,6 +93,12 @@
<ClCompile Include="..\..\src\core\mac\mac_whitelist.cpp">
<Filter>Source Files\mac</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\net\dhcp6_client.cpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\net\dhcp6_server.cpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\net\icmp6.cpp">
<Filter>Source Files\net</Filter>
</ClCompile>
@@ -213,7 +219,7 @@
<ClCompile Include="..\..\src\core\crypto\sha256.cpp">
<Filter>Source Files\crypto</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\utils\global_address.cpp">
<ClCompile Include="..\..\src\core\utils\slaac_address.cpp">
<Filter>Source Files\utils</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp">
@@ -278,6 +284,15 @@
<ClInclude Include="..\..\src\core\mac\mac_whitelist.hpp">
<Filter>Header Files\mac</Filter>
</ClInclude>
<ClCompile Include="..\..\src\core\net\dhcp6.hpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\net\dhcp6_client.hpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\net\dhcp6_server.hpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClInclude Include="..\..\src\core\net\icmp6.hpp">
<Filter>Header Files\net</Filter>
</ClInclude>
@@ -413,7 +428,7 @@
<ClInclude Include="..\..\src\core\crypto\sha256.hpp">
<Filter>Header Files\crypto</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\utils\global_address.hpp">
<ClInclude Include="..\..\src\core\utils\slaac_address.hpp">
<Filter>Header Files\utils</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\meshcop\announce_begin_server.hpp">
+8
View File
@@ -65,6 +65,14 @@ ifeq ($(JOINER),1)
configure_OPTIONS += --enable-joiner
endif
ifeq ($(DHCP6_SERVER),1)
configure_OPTIONS += --enable-dhcp6-server
endif
ifeq ($(DHCP6_CLIENT),1)
configure_OPTIONS += --enable-dhcp6-client
endif
COMMONCFLAGS := \
-fdata-sections \
-ffunction-sections \
+1 -1
View File
@@ -92,7 +92,7 @@ configure_OPTIONS = \
$(NULL)
ifeq ($(COVERAGE),1)
configure_OPTIONS += --enable-coverage --enable-commissioner --enable-joiner
configure_OPTIONS += --enable-coverage --enable-commissioner --enable-joiner --enable-dhcp6-client --enable-dhcp6-server
else
configure_OPTIONS +=
endif
+3
View File
@@ -33,6 +33,7 @@ include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
DIST_SUBDIRS = \
cli \
commissioning \
dhcp6 \
ncp \
platform \
$(NULL)
@@ -42,6 +43,7 @@ DIST_SUBDIRS = \
SUBDIRS = \
cli \
commissioning \
dhcp6 \
ncp \
platform \
$(NULL)
@@ -51,6 +53,7 @@ SUBDIRS = \
PRETTY_SUBDIRS = \
cli \
commissioning \
dhcp6 \
ncp \
platform \
$(NULL)
+40
View File
@@ -0,0 +1,40 @@
#
# 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.
#
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
ot_dhcp6_headers = \
dhcp6_client.h \
$(NULL)
ot_dhcp6dir = $(includedir)/dhcp6
dist_ot_dhcp6_HEADERS = $(ot_dhcp6_headers)
install-headers: install-includeHEADERS
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
+69
View File
@@ -0,0 +1,69 @@
/*
* 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
* @brief
* This file includes the platform abstraction for the Thread DHCPv6 client.
*/
#ifndef OPENTHREAD_DHCP6_CLIENT_H_
#define OPENTHREAD_DHCP6_CLIENT_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup core-dhcp6-client
*
* @{
*
*/
/**
* Update all automatically created IPv6 addresses for prefixes from current Network Data with DHCP 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] aContext A pointer to data passed to aIidCreate function.
*
*/
void otDhcp6ClientUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses, void *aContext);
/**
* @}
*
*/
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif // OPENTHREAD_DHCP6_CLIENT_H_
+5
View File
@@ -605,6 +605,11 @@ typedef struct otBorderRouterConfig
* TRUE, if this configuration is considered Stable Network Data. FALSE, otherwise.
*/
bool mStable : 1;
/**
* The Border Agent Rloc.
*/
uint16_t mRloc16;
} otBorderRouterConfig;
/**
+6
View File
@@ -38,6 +38,12 @@
/* Define to 1 to enable the joiner role. */
#define OPENTHREAD_ENABLE_JOINER 1
/* Define to 1 to enable DHCPv6 Client. */
#define OPENTHREAD_ENABLE_DHCP6_CLIENT 0
/* Define to 1 to enable DHCPv6 SERVER. */
#define OPENTHREAD_ENABLE_DHCP6_SERVER 0
/* Name of package */
#define PACKAGE "openthread"
+9 -1
View File
@@ -46,6 +46,7 @@
#include <openthread-diag.h>
#include <commissioning/commissioner.h>
#include <commissioning/joiner.h>
#include <dhcp6/dhcp6_client.h>
#include "cli.hpp"
#include "cli_dataset.hpp"
@@ -2469,8 +2470,15 @@ void Interpreter::HandleNetifStateChanged(uint32_t aFlags)
{
VerifyOrExit((aFlags & OT_THREAD_NETDATA_UPDATED) != 0, ;);
otSlaacUpdate(mInstance, mAutoAddresses, sizeof(mAutoAddresses) / sizeof(mAutoAddresses[0]), otCreateRandomIid,
otSlaacUpdate(mInstance, mSlaacAddresses, sizeof(mSlaacAddresses) / sizeof(mSlaacAddresses[0]), otCreateRandomIid,
NULL);
#if OPENTHREAD_ENABLE_DHCP6_SERVER
mInstance->mThreadNetif.GetDhcp6Server().UpdateService();
#endif // OPENTHREAD_ENABLE_DHCP6_SERVER
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
otDhcp6ClientUpdate(mInstance, mDhcpAddresses, sizeof(mDhcpAddresses) / sizeof(mDhcpAddresses[0]), NULL);
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
exit:
return;
+5 -1
View File
@@ -45,6 +45,7 @@
#include <cli/cli_server.hpp>
#include <net/icmp6.hpp>
#include <common/timer.hpp>
#include <dhcp6/dhcp6_client.h>
namespace Thread {
@@ -234,7 +235,10 @@ private:
uint32_t sInterval;
Timer sPingTimer;
otNetifAddress mAutoAddresses[kMaxAutoAddresses];
otNetifAddress mSlaacAddresses[OPENTHREAD_CONFIG_NUM_SLAAC_ADDRESSES];
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
otNetifAddress mDhcpAddresses[OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES];
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
otInstance *mInstance;
};
+17 -2
View File
@@ -87,7 +87,7 @@ libopenthread_a_SOURCES = \
thread/network_diag_tlvs.cpp \
thread/thread_netif.cpp \
thread/thread_tlvs.cpp \
utils/global_address.cpp \
utils/slaac_address.cpp \
$(NULL)
if OPENTHREAD_ENABLE_COMMISSIONER
@@ -111,6 +111,18 @@ libopenthread_a_SOURCES += \
$(NULL)
endif # OPENTHREAD_ENABLE_DTLS
if OPENTHREAD_ENABLE_DHCP6_CLIENT
libopenthread_a_SOURCES += \
net/dhcp6_client.cpp \
$(NULL)
endif # OPENTHREAD_ENABLE_DHCP6_CLIENT
if OPENTHREAD_ENABLE_DHCP6_SERVER
libopenthread_a_SOURCES += \
net/dhcp6_server.cpp \
$(NULL)
endif # OPENTHREAD_ENABLE_DHCP6_SERVER
noinst_HEADERS = \
openthread-core-config.h \
openthread-core-default-config.h \
@@ -157,6 +169,9 @@ noinst_HEADERS = \
net/socket.hpp \
net/udp6.hpp \
net/tcp.hpp \
net/dhcp6.hpp \
net/dhcp6_client.hpp \
net/dhcp6_server.hpp \
thread/address_resolver.hpp \
thread/announce_begin_server.hpp \
thread/energy_scan_server.hpp \
@@ -183,7 +198,7 @@ noinst_HEADERS = \
thread/thread_tlvs.hpp \
thread/thread_uris.hpp \
thread/topology.hpp \
utils/global_address.hpp \
utils/slaac_address.hpp \
$(NULL)
if OPENTHREAD_BUILD_COVERAGE
+585
View File
@@ -0,0 +1,585 @@
/*
* 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 DHCPv6 Service.
*/
#ifndef DHCP6_HPP_
#define DHCP6_HPP_
#include <common/message.hpp>
#include <net/udp6.hpp>
using Thread::Encoding::BigEndian::HostSwap16;
using Thread::Encoding::BigEndian::HostSwap32;
namespace Thread {
namespace Dhcp6 {
/**
* @addtogroup core-dhcp6
*
* @brief
* This module includes definitions for DHCPv6.
*
* @{
*
*/
/**
* DHCPv6 constant
*
*/
enum
{
kDhcpClientPort = 546,
kDhcpServerPort = 547,
kTransactionIdSize = 3,
kLinkLayerAddressLen = 8,
kHardwareTypeEui64 = 27,
};
/**
* DHCPv6 Message Types
*
*/
typedef enum Type
{
kTypeSolicit = 1,
kTypeAdvertise = 2,
kTypeRequest = 3,
kTypeConfirm = 4,
kTypeRenew = 5,
kTypeRebind = 6,
kTypeReply = 7,
kTypeRelease = 8,
kTypeDecline = 9,
kTypeReconfigure = 10,
kTypeInformationRequest = 11,
kTypeRelayForward = 12,
kTypeRelayReply = 13,
kTypeLeaseQuery = 14,
kTypeLeaseQueryReply = 15,
} Type;
/**
* This class implements DHCPv6 header.
*
*/
OT_TOOL_PACKED_BEGIN
class Dhcp6Header
{
public:
/**
* This method initializes the DHCPv6 header to all zeros.
*
*/
void Init(void) { mType = 0; mTransactionId[0] = 0; }
/**
* This method returns the DHCPv6 message type.
*
* @returns The DHCPv6 message type.
*
*/
Type GetType(void) const { return static_cast<Type>(mType); }
/**
* This method sets the DHCPv6 message type.
*
* @param[in] aType The DHCPv6 message type.
*
*/
void SetType(Type aType) { mType = static_cast<uint8_t>(aType); }
/**
* This method returns the DHCPv6 message transaction id.
*
* @returns A pointer of DHCPv6 message transaction id.
*
*/
uint8_t *GetTransactionId(void) { return mTransactionId; }
/**
* This method sets the DHCPv6 message transaction id.
*
* @param[in] aBuf The DHCPv6 message transaction id.
*
*/
void SetTransactionId(uint8_t *aBuf) { memcpy(mTransactionId, aBuf, kTransactionIdSize); }
private:
uint8_t mType; ///< Type
uint8_t mTransactionId[kTransactionIdSize]; ///< Transaction Id
} OT_TOOL_PACKED_END;
/**
* DHCPv6 Option Codes
*
*/
typedef enum Code
{
kOptionClientIdentifier = 1,
kOptionServerIdentifier = 2,
kOptionIaNa = 3,
kOptionIaTa = 4,
kOptionIaAddress = 5,
kOptionRequestOption = 6,
kOptionPreference = 7,
kOptionElapsedTime = 8,
kOptionRelayMessage = 9,
kOptionAuthentication = 11,
kOptionServerUnicast = 12,
kOptionStatusCode = 13,
kOptionRapidCommit = 14,
kOptionUserClass = 15,
kOptionVendorClass = 16,
kOptionVendorSpecificInformation = 17,
kOptionInterfaceId = 18,
kOptionReconfigureMessage = 19,
kOptionReconfigureAccept = 20,
kOptionLeaseQuery = 44,
kOptionClientData = 45,
kOptionClientLastTransactionTime = 46,
} Code;
/**
* This class implements DHCPv6 option.
*
*/
OT_TOOL_PACKED_BEGIN
class Dhcp6Option
{
public:
/**
* This method initializes the DHCPv6 option to all zeros.
*
*/
void Init(void) { mCode = 0; mLength = 0; }
/**
* This method returns the DHCPv6 option code.
*
* @returns The DHCPv6 option code.
*
*/
Code GetCode(void) const { return static_cast<Code>(HostSwap16(mCode)); }
/**
* This method sets the DHCPv6 option code.
*
* @param[in] aCode The DHCPv6 option code.
*
*/
void SetCode(Code aCode) { mCode = HostSwap16(static_cast<uint16_t>(aCode)); }
/**
* This method returns the Length of DHCPv6 option.
*
* @returns The length of DHCPv6 option.
*
*/
uint16_t GetLength(void) const { return HostSwap16(mLength); }
/**
* This method sets the length of DHCPv6 option.
*
* @param[in] aLength The length of DHCPv6 option.
*
*/
void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
private:
uint16_t mCode; ///< Code
uint16_t mLength; ///< Length
} OT_TOOL_PACKED_END;
/**
* Duid Type
*
*/
typedef enum DuidType
{
kDuidLLT = 1,
kDuidEN = 2,
kDuidLL = 3,
} DuidType;
OT_TOOL_PACKED_BEGIN
class ClientIdentifier: public Dhcp6Option
{
public:
/**
* This method initializes the DHCPv6 Option.
*
*/
void Init(void) { SetCode(kOptionClientIdentifier); SetLength(sizeof(*this) - sizeof(Dhcp6Option)); }
/**
* This method returns the client Duid Type.
*
* @returns The client Duid Type.
*
*/
DuidType GetDuidType(void) const { return static_cast<DuidType>(HostSwap16(mDuidType)); }
/**
* This method sets the client Duid Type.
*
* @param[in] aDuidType The client Duid Type.
*
*/
void SetDuidType(DuidType aDuidType) { mDuidType = HostSwap16(static_cast<uint16_t>(aDuidType)); }
/**
* This method returns the client Duid HardwareType.
*
* @returns The client Duid HardwareType.
*
*/
uint16_t GetDuidHardwareType(void) const { return HostSwap16(mDuidHardwareType); }
/**
* This method sets the client Duid HardwareType.
*
* @param[in] aDuidHardwareType The client Duid HardwareType.
*
*/
void SetDuidHardwareType(uint16_t aDuidHardwareType) { mDuidHardwareType = HostSwap16(aDuidHardwareType); }
/**
* This method returns the client LinkLayerAddress.
*
* @returns A pointer to the client LinkLayerAddress.
*
*/
uint8_t *GetDuidLinkLayerAddress(void) { return mDuidLinkLayerAddress; }
/**
* This method sets the client LinkLayerAddress.
*
* @param[in] aLinkLayerAddress The client LinkLayerAddress.
*
*/
void SetDuidLinkLayerAddress(const Mac::ExtAddress *aDuidLinkLayerAddress) { memcpy(mDuidLinkLayerAddress, aDuidLinkLayerAddress, sizeof(Mac::ExtAddress)); }
private:
uint16_t mDuidType; ///< Duid Type
uint16_t mDuidHardwareType; ///< Duid HardwareType
uint8_t mDuidLinkLayerAddress[kLinkLayerAddressLen]; ///< Duid LinkLayerAddress
} OT_TOOL_PACKED_END;
OT_TOOL_PACKED_BEGIN
class ServerIdentifier: public Dhcp6Option
{
public:
/**
* This method initializes the DHCPv6 Option.
*
*/
void Init(void) { SetCode(kOptionServerIdentifier); SetLength(sizeof(*this) - sizeof(Dhcp6Option)); }
/**
* This method returns the server Duid Type.
*
* @returns The server Duid Type.
*
*/
DuidType GetDuidType(void) const { return static_cast<DuidType>(HostSwap16(mDuidType)); }
/**
* This method sets the server Duid Type.
*
* @param[in] aDuidType The server Duid Type.
*
*/
void SetDuidType(DuidType aDuidType) { mDuidType = HostSwap16(static_cast<uint16_t>(aDuidType)); }
/**
* This method returns the server Duid HardwareType.
*
* @returns The server Duid HardwareType.
*
*/
uint16_t GetDuidHardwareType(void) const { return HostSwap16(mDuidHardwareType); }
/**
* This method sets the server Duid HardwareType.
*
* @param[in] aDuidHardwareType The server Duid HardwareType.
*
*/
void SetDuidHardwareType(uint16_t aDuidHardwareType) { mDuidHardwareType = HostSwap16(aDuidHardwareType); }
/**
* This method returns the server LinkLayerAddress.
*
* @returns A pointer to the server LinkLayerAddress.
*
*/
uint8_t *GetDuidLinkLayerAddress(void) { return mDuidLinkLayerAddress; }
/**
* This method sets the server LinkLayerAddress.
*
* @param[in] aLinkLayerAddress The server LinkLayerAddress.
*
*/
void SetDuidLinkLayerAddress(const Mac::ExtAddress *aDuidLinkLayerAddress) { memcpy(mDuidLinkLayerAddress, aDuidLinkLayerAddress, sizeof(Mac::ExtAddress)); }
private:
uint16_t mDuidType; ///< Duid Type
uint16_t mDuidHardwareType; ///< Duid HardwareType
uint8_t mDuidLinkLayerAddress[kLinkLayerAddressLen]; ///< Duid LinkLayerAddress
} OT_TOOL_PACKED_END;
OT_TOOL_PACKED_BEGIN
class IaNa: public Dhcp6Option
{
public:
/**
* This method initializes the DHCPv6 Option.
*
*/
void Init(void) { SetCode(kOptionIaNa); SetLength(sizeof(*this) - sizeof(Dhcp6Option)); }
/**
* This method returns client IAID.
*
* @returns The client IAID.
*
*/
uint32_t GetIaid(void) const { return HostSwap32(mIaid); }
/**
* This method sets the client IAID.
*
* @param[in] aIaId The client IAID.
*
*/
void SetIaid(uint32_t aIaid) { mIaid = HostSwap32(aIaid); }
/**
* This method returns T1.
*
* @returns The value of T1.
*
*/
uint32_t GetT1(void) const { return HostSwap32(mT1); }
/**
* This method sets the value of T1.
*
* @param[in] aT1 The value of T1.
*
*/
void SetT1(uint32_t aT1) { mT1 = HostSwap32(aT1); }
/**
* This method returns T2.
*
* @returns The value of T2.
*
*/
uint32_t GetT2(void) const { return HostSwap32(mT2); }
/**
* This method sets the value of T2.
*
* @param[in] aT2 The value of T2.
*
*/
void SetT2(uint32_t aT2) { mT2 = HostSwap32(aT2); }
private:
uint32_t mIaid; ///< IAID
uint32_t mT1; ///< T1
uint32_t mT2; ///< T2
} OT_TOOL_PACKED_END;
OT_TOOL_PACKED_BEGIN
class IaAddress: public Dhcp6Option
{
public:
/**
* This method initializes the DHCPv6 Option.
*
*/
void Init(void) { SetCode(kOptionIaAddress); SetLength(sizeof(*this) - sizeof(Dhcp6Option)); }
/**
* This method returns the pointer to the IPv6 address.
*
* @returns A pointer to the IPv6 address.
*
*/
otIp6Address *GetAddress(void) { return &mAddress; }
/**
* This method sets the IPv6 address.
*
* @param[in] aAddress The reference to the IPv6 address to set.
*
*/
void SetAddress(otIp6Address &aAddress) { memcpy(mAddress.mFields.m8, aAddress.mFields.m8, sizeof(otIp6Address)); }
/**
* This method returns the preferred lifetime of the IPv6 address.
*
* @returns The preferred lifetime of the IPv6 address.
*
*/
uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
/**
* This method sets the preferred lifetime of the IPv6 address.
*
* @param[in] aPreferredLifetime The preferred lifetime of the IPv6 address.
*
*/
void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
/**
* This method returns the valid lifetime of the IPv6 address.
*
* @returns The valid lifetime of the IPv6 address.
*
*/
uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
/**
* This method sets the valid lifetime of the IPv6 address.
*
* @param[in] aValidLifetime The valid lifetime of the IPv6 address.
*
*/
void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
private:
otIp6Address mAddress; ///< IPv6 address
uint32_t mPreferredLifetime; ///< Preferred Lifetime
uint32_t mValidLifetime; ///< Valid Lifetime
} OT_TOOL_PACKED_END;
OT_TOOL_PACKED_BEGIN
class ElapsedTime: public Dhcp6Option
{
public:
/**
* This method initializes the DHCPv6 Option.
*
*/
void Init(void) { SetCode(kOptionElapsedTime); SetLength(sizeof(*this) - sizeof(Dhcp6Option)); }
/**
* This method returns the elapsed time since solicit starts.
*
* @returns The elapsed time since solicit starts.
*
*/
uint16_t GetElapsedTime(void) const { return HostSwap16(mElapsedTime); }
/**
* This method sets the elapsed time since solicit starts.
*
* @param[in] aElapsedTime The elapsed time since solicit starts.
*
*/
void SetElapsedTime(uint16_t aElapsedTime) { mElapsedTime = HostSwap16(aElapsedTime); }
private:
uint16_t mElapsedTime; ///< Elapsed time
} OT_TOOL_PACKED_END;
/**
* Status Code
*
*/
typedef enum Status
{
kStatusSuccess = 0,
kStatusUnspecFail = 1,
kStatusNoAddrsAvail = 2,
kStatusNoBinding = 3,
kStatusNotOnLink = 4,
kStatusUseMulticast = 5,
kUnknownQueryType = 7,
kMalformedQuery = 8,
kNotConfigured = 9,
kNotAllowed = 10,
} Status;
OT_TOOL_PACKED_BEGIN
class StatusCode: public Dhcp6Option
{
public:
/**
* This method initializes the DHCPv6 Option.
*
*/
void Init(void) { SetCode(kOptionStatusCode); SetLength(sizeof(*this) - sizeof(Dhcp6Option)); }
/**
* This method returns the status code.
*
* @returns The status code.
*
*/
Status GetStatusCode(void) const { return static_cast<Status>(HostSwap16(mStatus)); }
/**
* This method sets the status code.
*
* @param[in] aStatus The status code.
*
*/
void SetStatusCode(Status aStatus) { mStatus = HostSwap16(static_cast<uint16_t>(aStatus)); }
private:
uint16_t mStatus; ///< Status Code
} OT_TOOL_PACKED_END;
OT_TOOL_PACKED_BEGIN
class RapidCommit: public Dhcp6Option
{
public:
/**
* This method initializes the DHCPv6 Option.
*
*/
void Init(void) { SetCode(kOptionRapidCommit); SetLength(sizeof(*this) - sizeof(Dhcp6Option)); }
} OT_TOOL_PACKED_END;
} // namespace Dhcp6
} // namespace Thread
#endif // DHCP6_HPP_
+704
View File
@@ -0,0 +1,704 @@
/*
* 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 DHCPv6 Client.
*/
#include <openthread-types.h>
#include <common/code_utils.hpp>
#include <common/encoding.hpp>
#include <common/logging.hpp>
#include <mac/mac.hpp>
#include <net/dhcp6.hpp>
#include <net/dhcp6_client.hpp>
#include <platform/random.h>
#include <thread/thread_netif.hpp>
using Thread::Encoding::BigEndian::HostSwap16;
using Thread::Encoding::BigEndian::HostSwap32;
namespace Thread {
namespace Dhcp6 {
Dhcp6Client::Dhcp6Client(ThreadNetif &aThreadNetif) :
mTrickleTimer(aThreadNetif.GetIp6().mTimerScheduler, &Dhcp6Client::HandleTrickleTimer, NULL, this),
mSocket(aThreadNetif.GetIp6().mUdp),
mMle(aThreadNetif.GetMle()),
mMac(aThreadNetif.GetMac()),
mNetif(aThreadNetif)
{
for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
memset(&(mIdentityAssociations[i]), 0, sizeof(IdentityAssociation));
}
for (uint8_t i = 0; i < (OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES - 1); i++)
{
mIdentityAssociations[i].SetNext(&(mIdentityAssociations[i+1]));
}
mIdentityAssociationHead = NULL;
mIdentityAssociationAvail = &mIdentityAssociations[0];
}
void Dhcp6Client::UpdateAddresses(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses, void *aContext)
{
(void)aContext;
bool found = false;;
bool newAgent = false;
otNetifAddress *address = NULL;
otNetworkDataIterator iterator;
otBorderRouterConfig config;
mAddresses = aAddresses;
mNumAddresses = aNumAddresses;
// remove addresses directly if prefix not valid in network data
for (uint8_t i = 0; i < mNumAddresses; i++)
{
address = &mAddresses[i];
if (address->mValidLifetime == 0)
{
continue;
}
found = false;
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
while ((otGetNextOnMeshPrefix(aInstance, false, &iterator, &config)) == kThreadError_None)
{
if (!config.mDhcp)
{
continue;
}
if ((otIp6PrefixMatch(&(address->mAddress), &(config.mPrefix.mPrefix)) >= address->mPrefixLength) &&
(config.mPrefix.mLength == address->mPrefixLength))
{
found = true;
break;
}
}
if (!found)
{
otRemoveUnicastAddress(aInstance, &(address->mAddress));
RemoveIdentityAssociation(config.mRloc16, config.mPrefix);
memset(address, 0, sizeof(*address));
}
}
// add IdentityAssociation for new configured prefix
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
while (otGetNextOnMeshPrefix(aInstance, false, &iterator, &config) == kThreadError_None)
{
if (!config.mDhcp)
{
continue;
}
found = false;
for (uint8_t i = 0; i < mNumAddresses; i++)
{
address = &mAddresses[i];
if (address->mPrefixLength == 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 < mNumAddresses; i++)
{
address = &mAddresses[i];
if (address->mPrefixLength != 0)
{
continue;
}
memset(address, 0, sizeof(*address));
// suppose all configured prefix are ::/64
memcpy(address->mAddress.mFields.m8, config.mPrefix.mPrefix.mFields.m8, 8);
address->mPrefixLength = config.mPrefix.mLength;
AddIdentityAssociation(config.mRloc16, config.mPrefix);
newAgent = true;
break;
}
}
}
if (newAgent)
{
Start();
}
else
{
Stop();
}
}
void Dhcp6Client::AddIdentityAssociation(uint16_t aRloc16, otIp6Prefix &aIp6Prefix)
{
IdentityAssociation *identityAssociation = NULL;
IdentityAssociation *identityAssociationCursor = NULL;
VerifyOrExit(mIdentityAssociationAvail, ;);
identityAssociation = mIdentityAssociationAvail;
mIdentityAssociationAvail = mIdentityAssociationAvail->GetNext();
identityAssociation->SetPrefixAgentRloc(aRloc16);
identityAssociation->SetPrefix(aIp6Prefix);
identityAssociation->SetStatus(IdentityAssociation::kStatusSolicit);
identityAssociation->SetNext(NULL);
if (mIdentityAssociationHead)
{
// append the new identityassociation to the tail of used list
for (identityAssociationCursor = mIdentityAssociationHead; identityAssociationCursor->GetNext();
identityAssociationCursor = identityAssociationCursor->GetNext()) {}
identityAssociationCursor->SetNext(identityAssociation);
}
else
{
mIdentityAssociationHead = identityAssociation;
}
exit:
{}
}
void Dhcp6Client::RemoveIdentityAssociation(uint16_t aRloc16, otIp6Prefix &aIp6Prefix)
{
IdentityAssociation *prevIdentityAssociation = NULL;
IdentityAssociation *identityAssociation = NULL;
VerifyOrExit(mIdentityAssociationHead, ;);
for (identityAssociation = mIdentityAssociationHead; identityAssociation;
prevIdentityAssociation = identityAssociation, identityAssociation = identityAssociation->GetNext())
{
if (identityAssociation->GetPrefixAgentRloc() != aRloc16)
{
continue;
}
if (otIp6PrefixMatch(&(aIp6Prefix.mPrefix), &(identityAssociation->GetPrefix()->mPrefix)) < aIp6Prefix.mLength)
{
continue;
}
// remove from used list
if (prevIdentityAssociation)
{
prevIdentityAssociation->SetNext(identityAssociation->GetNext());
}
else
{
mIdentityAssociationHead = identityAssociation->GetNext();
}
// return to available list
memset(identityAssociation, 0, sizeof(*identityAssociation));
identityAssociation->SetNext(mIdentityAssociationAvail);
mIdentityAssociationAvail = identityAssociation;
break;
}
exit:
{}
}
ThreadError Dhcp6Client::Start()
{
Ip6::SockAddr sockaddr;
sockaddr.mPort = kDhcpClientPort;
mSocket.Open(&Dhcp6Client::HandleUdpReceive, this);
mSocket.Bind(sockaddr);
ProcessNextIdentityAssociation();
return kThreadError_None;
}
ThreadError Dhcp6Client::Stop()
{
mSocket.Close();
return kThreadError_None;
}
bool Dhcp6Client::ProcessNextIdentityAssociation()
{
bool rval = false;
IdentityAssociation *prevIdentityAssociation = NULL;
IdentityAssociation *identityAssociation = NULL;
VerifyOrExit(mIdentityAssociationHead, ;);
// not interrupt in-progress solicit
VerifyOrExit((mIdentityAssociationHead->GetStatus() != IdentityAssociation::kStatusSoliciting), ;);
mTrickleTimer.Stop();
for (identityAssociation = mIdentityAssociationHead; identityAssociation;
prevIdentityAssociation = identityAssociation, identityAssociation = identityAssociation->GetNext())
{
if (identityAssociation->GetStatus() != IdentityAssociation::kStatusSolicit)
{
continue;
}
// new transaction id
for (uint8_t i = 0; i < kTransactionIdSize; i++)
{
mTransactionId[i] = static_cast<uint8_t>(otPlatRandomGet());
}
// ensure mIdentityAssociationHead is the prefix agent to solicit.
if (prevIdentityAssociation)
{
prevIdentityAssociation->SetNext(identityAssociation->GetNext());
identityAssociation->SetNext(mIdentityAssociationHead);
mIdentityAssociationHead = identityAssociation;
}
mTrickleTimer.Start(
Timer::SecToMsec(kTrickleTimerImin),
Timer::SecToMsec(kTrickleTimerImax),
TrickleTimer::kModeNormal);
mTrickleTimer.IndicateInconsistent();
ExitNow(rval = true);
}
exit:
return rval;
}
bool Dhcp6Client::HandleTrickleTimer(void *aContext)
{
Dhcp6Client *obj = static_cast<Dhcp6Client *>(aContext);
return obj->HandleTrickleTimer();
}
bool Dhcp6Client::HandleTrickleTimer(void)
{
bool rval = true;
VerifyOrExit(mIdentityAssociationHead, rval = false);
switch (mIdentityAssociationHead->GetStatus())
{
case IdentityAssociation::kStatusSolicit:
mStartTime = otPlatAlarmGetNow();
mIdentityAssociationHead->SetStatus(IdentityAssociation::kStatusSoliciting);
// fall through
case IdentityAssociation::kStatusSoliciting:
Solicit(mIdentityAssociationHead->GetPrefixAgentRloc());
break;
case IdentityAssociation::kStatusSolicitReplied:
if (!ProcessNextIdentityAssociation())
{
mTrickleTimer.Stop();
Stop();
rval = false;
}
break;
default:
break;
}
exit:
return rval;
}
ThreadError Dhcp6Client::Solicit(uint16_t aRloc16)
{
ThreadError error = kThreadError_None;
Message *message;
Ip6::MessageInfo messageInfo;
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
SuccessOrExit(error = AppendHeader(*message));
SuccessOrExit(error = AppendElapsedTime(*message));
SuccessOrExit(error = AppendClientIdentifier(*message));
SuccessOrExit(error = AppendIaNa(*message, aRloc16));
// specify which prefixes to solicit
SuccessOrExit(error = AppendIaAddress(*message, aRloc16));
SuccessOrExit(error = AppendRapidCommit(*message));
memset(&messageInfo, 0, sizeof(messageInfo));
memcpy(messageInfo.GetPeerAddr().mFields.m8, mMle.GetMeshLocalPrefix(), 8);
messageInfo.GetPeerAddr().mFields.m16[4] = HostSwap16(0x0000);
messageInfo.GetPeerAddr().mFields.m16[5] = HostSwap16(0x00ff);
messageInfo.GetPeerAddr().mFields.m16[6] = HostSwap16(0xfe00);
messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(aRloc16);
messageInfo.SetSockAddr(mMle.GetMeshLocal16());
messageInfo.mPeerPort = kDhcpServerPort;
messageInfo.mInterfaceId = mNetif.GetInterfaceId();
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
otLogInfoIp6("solicit\n");
exit:
if (message != NULL && error != kThreadError_None)
{
message->Free();
}
return error;
}
ThreadError Dhcp6Client::AppendHeader(Message &aMessage)
{
Dhcp6Header header;
header.Init();
header.SetType(kTypeSolicit);
header.SetTransactionId(mTransactionId);
return aMessage.Append(&header, sizeof(header));
}
ThreadError Dhcp6Client::AppendElapsedTime(Message &aMessage)
{
ElapsedTime option;
option.Init();
option.SetElapsedTime(static_cast<uint16_t>(Timer::MsecToSec(otPlatAlarmGetNow() - mStartTime)));
return aMessage.Append(&option, sizeof(option));
}
ThreadError Dhcp6Client::AppendClientIdentifier(Message &aMessage)
{
ClientIdentifier option;
option.Init();
option.SetDuidType(kDuidLL);
option.SetDuidHardwareType(kHardwareTypeEui64);
option.SetDuidLinkLayerAddress(mMac.GetExtAddress());
return aMessage.Append(&option, sizeof(option));
}
ThreadError Dhcp6Client::AppendIaNa(Message &aMessage, uint16_t aRloc16)
{
ThreadError error = kThreadError_None;
uint8_t count = 0;
uint16_t length = 0;
IdentityAssociation *identityAssociation = NULL;
IaNa option;
VerifyOrExit(mIdentityAssociationHead, error = kThreadError_Drop);
for (identityAssociation = mIdentityAssociationHead; identityAssociation; identityAssociation = identityAssociation->GetNext())
{
if (identityAssociation->GetStatus() == IdentityAssociation::kStatusSolicitReplied)
{
continue;
}
if (identityAssociation->GetPrefixAgentRloc() == aRloc16)
{
count++;
}
}
// compute the right length
length = sizeof(IaNa) + sizeof(IaAddress) * count - sizeof(Dhcp6Option);
option.Init();
option.SetLength(length);
option.SetIaid(0);
option.SetT1(0);
option.SetT2(0);
SuccessOrExit(error = aMessage.Append(&option, sizeof(IaNa)));
exit:
return error;
}
ThreadError Dhcp6Client::AppendIaAddress(Message &aMessage, uint16_t aRloc16)
{
ThreadError error = kThreadError_None;
IdentityAssociation *identityAssociation = NULL;
IaAddress option;
VerifyOrExit(mIdentityAssociationHead, error = kThreadError_Drop);
option.Init();
for (identityAssociation = mIdentityAssociationHead; identityAssociation; identityAssociation = identityAssociation->GetNext())
{
if ((identityAssociation->GetStatus() != IdentityAssociation::kStatusSolicitReplied) &&
(identityAssociation->GetPrefixAgentRloc() == aRloc16))
{
option.SetAddress(identityAssociation->GetPrefix()->mPrefix);
option.SetPreferredLifetime(0);
option.SetValidLifetime(0);
SuccessOrExit(error = aMessage.Append(&option, sizeof(option)));
}
}
exit:
return error;
}
ThreadError Dhcp6Client::AppendRapidCommit(Message &aMessage)
{
RapidCommit option;
option.Init();
return aMessage.Append(&option, sizeof(option));
}
void Dhcp6Client::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
{
Dhcp6Client *obj = static_cast<Dhcp6Client *>(aContext);
obj->HandleUdpReceive(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
void Dhcp6Client::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Dhcp6Header header;
(void)aMessageInfo;
VerifyOrExit(aMessage.GetLength() - aMessage.GetOffset() >= static_cast<uint16_t>(sizeof(Dhcp6Header)), ;);
aMessage.Read(aMessage.GetOffset(), sizeof(header), &header);
aMessage.MoveOffset(sizeof(header));
if ((header.GetType() == kTypeReply) && (!memcmp(header.GetTransactionId(), mTransactionId, kTransactionIdSize)))
{
ProcessReply(aMessage);
}
exit:
{}
}
void Dhcp6Client::ProcessReply(Message &aMessage)
{
uint16_t offset = aMessage.GetOffset();
uint16_t length = aMessage.GetLength() - aMessage.GetOffset();
uint16_t optionOffset;
// Server Identifier
VerifyOrExit((optionOffset = FindOption(aMessage, offset, length, kOptionServerIdentifier)) > 0, ;);
SuccessOrExit(ProcessServerIdentifier(aMessage, optionOffset));
// Client Identifier
VerifyOrExit((optionOffset = FindOption(aMessage, offset, length, kOptionClientIdentifier)) > 0, ;);
SuccessOrExit(ProcessClientIdentifier(aMessage, optionOffset));
// Rapid Commit
VerifyOrExit(FindOption(aMessage, offset, length, kOptionRapidCommit) > 0, ;);
// IA_NA
VerifyOrExit((optionOffset = FindOption(aMessage, offset, length, kOptionIaNa)) > 0, ;);
SuccessOrExit(ProcessIaNa(aMessage, optionOffset));
HandleTrickleTimer();
exit:
return;
}
uint16_t Dhcp6Client::FindOption(Message &aMessage, uint16_t aOffset, uint16_t aLength, Dhcp6::Code aCode)
{
uint16_t end = aOffset + aLength;
while (aOffset <= end)
{
Dhcp6Option option;
aMessage.Read(aOffset, sizeof(option), &option);
if (option.GetCode() == (aCode))
{
return aOffset;
}
aOffset += sizeof(option) + option.GetLength();
}
return 0;
}
ThreadError Dhcp6Client::ProcessServerIdentifier(Message &aMessage, uint16_t aOffset)
{
ThreadError error = kThreadError_None;
ServerIdentifier option;
VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) &&
(option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option))) &&
(option.GetDuidType() == kDuidLL) &&
(option.GetDuidHardwareType() == kHardwareTypeEui64)),
error = kThreadError_Parse);
exit:
return error;
}
ThreadError Dhcp6Client::ProcessClientIdentifier(Message &aMessage, uint16_t aOffset)
{
ThreadError error = kThreadError_None;
ClientIdentifier option;
VerifyOrExit((((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) &&
(option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option))) &&
(option.GetDuidType() == kDuidLL) &&
(option.GetDuidHardwareType() == kHardwareTypeEui64)) &&
(!memcmp(option.GetDuidLinkLayerAddress(), mMac.GetExtAddress(), sizeof(Mac::ExtAddress)))),
error = kThreadError_Parse);
exit:
return error;
}
ThreadError Dhcp6Client::ProcessIaNa(Message &aMessage, uint16_t aOffset)
{
ThreadError error = kThreadError_None;
IaNa option;
uint16_t optionOffset;
uint16_t length;
VerifyOrExit(aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option), error = kThreadError_Parse);
aOffset += sizeof(option);
length = option.GetLength();
if ((optionOffset = FindOption(aMessage, aOffset, length, kOptionStatusCode)) > 0)
{
SuccessOrExit(error = ProcessStatusCode(aMessage, optionOffset));
}
while (length > 0)
{
if ((optionOffset = FindOption(aMessage, aOffset, length, kOptionIaAddress)) == 0)
{
ExitNow();
}
SuccessOrExit(error = ProcessIaAddress(aMessage, optionOffset));
length -= ((optionOffset - aOffset) + sizeof(IaAddress));
aOffset = optionOffset + sizeof(IaAddress);
}
exit:
return error;
}
ThreadError Dhcp6Client::ProcessStatusCode(Message &aMessage, uint16_t aOffset)
{
ThreadError error = kThreadError_None;
StatusCode option;
VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) &&
(option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option))) &&
(option.GetStatusCode() == kStatusSuccess)),
error = kThreadError_Parse);
exit:
return error;
}
ThreadError Dhcp6Client::ProcessIaAddress(Message &aMessage, uint16_t aOffset)
{
ThreadError error = kThreadError_None;
IdentityAssociation *identityAssociation = NULL;
otNetifAddress *address = NULL;
otIp6Prefix *prefix = NULL;
IaAddress option;
VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) &&
(option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option)))),
error = kThreadError_Parse);
for (uint8_t i = 0; i < mNumAddresses; i++)
{
address = &mAddresses[i];
if (address->mValidLifetime != 0)
{
continue;
}
if (otIp6PrefixMatch(&(address->mAddress), option.GetAddress()) >= address->mPrefixLength)
{
memcpy(address->mAddress.mFields.m8, option.GetAddress()->mFields.m8, sizeof(otIp6Address));
address->mPreferredLifetime = option.GetPreferredLifetime();
address->mValidLifetime = option.GetValidLifetime();
otAddUnicastAddress(mNetif.GetInstance(), address);
break;
}
}
// mark IdentityAssociation as replied
for (identityAssociation = mIdentityAssociationHead; identityAssociation; identityAssociation = identityAssociation->GetNext())
{
prefix = identityAssociation->GetPrefix();
if (otIp6PrefixMatch(option.GetAddress(), &(prefix->mPrefix)) >= prefix->mLength)
{
identityAssociation->SetStatus(IdentityAssociation::kStatusSolicitReplied);
break;
}
}
exit:
return error;
}
} // namespace Dhcp6
} // namespace Thread
+242
View File
@@ -0,0 +1,242 @@
/*
* 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 DHCPv6 Client.
*/
#ifndef DHCP6_CLIENT_HPP_
#define DHCP6_CLIENT_HPP_
#include <common/message.hpp>
#include <common/timer.hpp>
#include <common/trickle_timer.hpp>
#include <mac/mac.hpp>
#include <mac/mac_frame.hpp>
#include <net/dhcp6.hpp>
#include <net/udp6.hpp>
namespace Thread {
class ThreadNetif;
namespace Mle { class MleRouter; }
namespace Dhcp6 {
/**
* @addtogroup core-dhcp6
*
* @brief
* This module includes definitions for DHCPv6 Client.
*
* @{
*
*/
/**
* Some constants
*
*/
enum
{
kTrickleTimerImin = 1,
kTrickleTimerImax = 120,
};
/**
* This class implements IdentityAssociation.
*
*/
OT_TOOL_PACKED_BEGIN
class IdentityAssociation
{
public:
/**
* Status of IdentityAssociation
*
*/
typedef enum Status
{
kStatusInvalid,
kStatusSolicit,
kStatusSoliciting,
kStatusSolicitReplied,
} Status;
/**
* This method returns the status of the object.
*
* @returns Status.
*
*/
Status GetStatus(void) const { return static_cast<Status>(mStatus); }
/**
* This method sets the status of the object.
*
* @param[in] aStatus The Status to set.
*
*/
void SetStatus(Status aStatus) { mStatus = static_cast<uint8_t>(aStatus); }
/**
* This method returns the rloc of the DHCP Agent.
*
* @returns Status.
*
*/
uint16_t GetPrefixAgentRloc(void) const { return mPrefixAgentRloc; }
/**
* This method sets the rloc of the DHCP Agent.
*
* @param[in] aRloc The rloc of the DHCP Agent.
*
*/
void SetPrefixAgentRloc(uint16_t aRloc16) { mPrefixAgentRloc = aRloc16; }
/**
* This method returns the pointer to the IPv6 prefix.
*
* @returns A pointer to the IPv6 prefix.
*
*/
otIp6Prefix *GetPrefix(void) { return &mIp6Prefix; }
/**
* This method sets the IPv6 prefix to specified location.
*
* @param[in] aIp6Prefix The reference to the IPv6 prefix to set.
*
*/
void SetPrefix(otIp6Prefix &aIp6Prefix) { memcpy(&mIp6Prefix, &aIp6Prefix, sizeof(otIp6Prefix)); }
/**
* This method returns the pointer to the next IdentityAssociation.
*
* @returns A pointer to the next IdentityAssociation.
*
*/
IdentityAssociation *GetNext(void) { return mNext; }
/**
* This method sets the pointer to the next IdentityAssociation.
*
*/
void SetNext(IdentityAssociation *aNext) { mNext = aNext; }
private:
uint8_t mStatus; ///< Status of IdentityAssocation
uint16_t mPrefixAgentRloc; ///< Rloc of Prefix Agent
otIp6Prefix mIp6Prefix; ///< Prefix
IdentityAssociation *mNext; ///< Pointer to next IdentityAssocation
} OT_TOOL_PACKED_END;
/**
* This class implements DHCPv6 Client.
*
*/
class Dhcp6Client
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aThreadNetif A reference to the Thread network interface.
*
*/
explicit Dhcp6Client(ThreadNetif &aThreadNetif);
/**
* This function update addresses that shall be automatically created using DHCP.
*
* @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] aContext A pointer to IID creator-specific context data.
*
*/
void UpdateAddresses(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses, void *aContext);
private:
ThreadError Start(void);
ThreadError Stop(void);
ThreadError Solicit(uint16_t aRloc16);
void AddIdentityAssociation(uint16_t aRloc16, otIp6Prefix &aIp6Prefix);
void RemoveIdentityAssociation(uint16_t aRloc16, otIp6Prefix &aIp6Prefix);
bool ProcessNextIdentityAssociation(void);
ThreadError AppendHeader(Message &aMessage);
ThreadError AppendClientIdentifier(Message &aMessage);
ThreadError AppendIaNa(Message &aMessage, uint16_t aRloc16);
ThreadError AppendIaAddress(Message &aMessage, uint16_t aRloc16);
ThreadError AppendElapsedTime(Message &aMessage);
ThreadError AppendRapidCommit(Message &aMessage);
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessReply(Message &aMessage);
uint16_t FindOption(Message &aMessage, uint16_t aOffset, uint16_t aLength, Code aCode);
ThreadError ProcessServerIdentifier(Message &aMessage, uint16_t aOffset);
ThreadError ProcessClientIdentifier(Message &aMessage, uint16_t aOffset);
ThreadError ProcessIaNa(Message &aMessage, uint16_t aOffset);
ThreadError ProcessStatusCode(Message &aMessage, uint16_t aOffset);
ThreadError ProcessIaAddress(Message &aMessage, uint16_t aOffset);
static bool HandleTrickleTimer(void *aContext);
bool HandleTrickleTimer(void);
TrickleTimer mTrickleTimer;
Ip6::UdpSocket mSocket;
Mle::MleRouter &mMle;
Mac::Mac &mMac;
ThreadNetif &mNetif;
uint8_t mTransactionId[kTransactionIdSize];
uint32_t mStartTime;
otNetifAddress *mAddresses;
uint32_t mNumAddresses;
IdentityAssociation mIdentityAssociations[OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES];
IdentityAssociation *mIdentityAssociationHead;
IdentityAssociation *mIdentityAssociationAvail;
};
} // namespace Dhcp6
} // namespace Thread
# endif // DHCP6_CLIENT_HPP_
+566
View File
@@ -0,0 +1,566 @@
/*
* 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 DHCPv6 Server.
*/
#include <openthread-types.h>
#include <common/code_utils.hpp>
#include <common/encoding.hpp>
#include <common/logging.hpp>
#include <net/dhcp6_server.hpp>
#include <thread/mle.hpp>
#include <thread/thread_netif.hpp>
using Thread::Encoding::BigEndian::HostSwap16;
using Thread::Encoding::BigEndian::HostSwap32;
namespace Thread {
namespace Dhcp6 {
Dhcp6Server::Dhcp6Server(ThreadNetif &aThreadNetif):
mSocket(aThreadNetif.GetIp6().mUdp),
mMac(aThreadNetif.GetMac()),
mMle(aThreadNetif.GetMle()),
mNetworkDataLeader(aThreadNetif.GetNetworkDataLeader()),
mNetif(aThreadNetif)
{
for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
memset(&(mPrefixAgents[i]), 0, sizeof(PrefixAgent));
memset(&mAgentsAloc[i], 0, sizeof(mAgentsAloc[i]));
}
mPrefixAgentsCount = 0;
mPrefixAgentsMask = 0;
}
ThreadError Dhcp6Server::UpdateService()
{
ThreadError error = kThreadError_None;
bool found;
uint8_t i;
uint16_t rloc16 = mMle.GetRloc16();
Ip6::Address *address = NULL;
otNetworkDataIterator iterator;
otBorderRouterConfig config;
Lowpan::Context lowpanContext;
// remove dhcp agent aloc and prefix delegation
for (i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
found = false;
if (mAgentsAloc[i].mValidLifetime == 0)
{
continue;
}
address = &(mAgentsAloc[i].GetAddress());
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
while (mNetworkDataLeader.GetNextOnMeshPrefix(&iterator, rloc16, &config) == kThreadError_None)
{
if (!config.mDhcp)
{
continue;
}
mNetworkDataLeader.GetContext(*static_cast<const Ip6::Address *>(&(config.mPrefix.mPrefix)), lowpanContext);
if (address->mFields.m8[15] == lowpanContext.mContextId)
{
// still in network data
found = true;
break;
}
}
if (!found)
{
mNetworkDataLeader.GetContext(address->mFields.m8[15], lowpanContext);
mNetif.RemoveUnicastAddress(mAgentsAloc[i]);
mAgentsAloc[i].mValidLifetime = 0;
RemovePrefixAgent(lowpanContext.mPrefix);
}
}
// add dhcp agent aloc and prefix delegation
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
while (mNetworkDataLeader.GetNextOnMeshPrefix(&iterator, rloc16, &config) == kThreadError_None)
{
if (!config.mDhcp)
{
continue;
}
mNetworkDataLeader.GetContext(*static_cast<const Ip6::Address *>(&config.mPrefix.mPrefix), lowpanContext);
for (i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
found = false;
address = &(mAgentsAloc[i].GetAddress());
if ((mAgentsAloc[i].mValidLifetime != 0) && (address->mFields.m8[15] == lowpanContext.mContextId))
{
found = true;
break;
}
}
// alreay added
if (found)
{
continue;
}
for (i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
if (mAgentsAloc[i].mValidLifetime == 0)
{
address = &(mAgentsAloc[i].GetAddress());
memcpy(address, mMle.GetMeshLocalPrefix(), 8);
address->mFields.m16[4] = HostSwap16(0x0000);
address->mFields.m16[5] = HostSwap16(0x00ff);
address->mFields.m16[6] = HostSwap16(0xfe00);
address->mFields.m8[14] = Mle::kAloc16Mask;
address->mFields.m8[15] = lowpanContext.mContextId;
mAgentsAloc[i].mPrefixLength = 128;
mAgentsAloc[i].mPreferredLifetime = 0xffffffff;
mAgentsAloc[i].mValidLifetime = 0xffffffff;
mNetif.AddUnicastAddress(mAgentsAloc[i]);
AddPrefixAgent(config.mPrefix);
break;
}
}
// if no available Dhcp Agent Aloc resources
if (i == OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES)
{
ExitNow(error = kThreadError_NoBufs);
}
}
if (mPrefixAgentsCount > 0)
{
Start();
}
else
{
Stop();
}
exit:
return error;
}
ThreadError Dhcp6Server::Start()
{
Ip6::SockAddr sockaddr;
sockaddr.mPort = kDhcpServerPort;
mSocket.Open(&Dhcp6Server::HandleUdpReceive, this);
mSocket.Bind(sockaddr);
return kThreadError_None;
}
ThreadError Dhcp6Server::Stop()
{
mSocket.Close();
return kThreadError_None;
}
ThreadError Dhcp6Server::AddPrefixAgent(otIp6Prefix &aIp6Prefix)
{
ThreadError error = kThreadError_NoBufs;
for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
if (mPrefixAgents[i].GetPrefix()->mLength != 0)
{
continue;
}
mPrefixAgents[i].SetPrefix(aIp6Prefix);
mPrefixAgentsCount++;
ExitNow(error = kThreadError_None);
}
exit:
return error;
}
ThreadError Dhcp6Server::RemovePrefixAgent(const uint8_t *aIp6Address)
{
ThreadError error = kThreadError_NotFound;
otIp6Prefix *prefix = NULL;
for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
prefix = mPrefixAgents[i].GetPrefix();
if (prefix->mLength == 0)
{
continue;
}
if (otIp6PrefixMatch(&(prefix->mPrefix), reinterpret_cast<const otIp6Address*>(aIp6Address)) >= prefix->mLength)
{
memset(&(mPrefixAgents[i]), 0, sizeof(PrefixAgent));
mPrefixAgentsCount--;
ExitNow(error = kThreadError_None);
}
}
exit:
return error;
}
void Dhcp6Server::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
{
Dhcp6Server *obj = static_cast<Dhcp6Server *>(aContext);
obj->HandleUdpReceive(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
void Dhcp6Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Dhcp6Header header;
otIp6Address dst = aMessageInfo.mPeerAddr;
VerifyOrExit(aMessage.GetLength() - aMessage.GetOffset() >= static_cast<uint16_t>(sizeof(Dhcp6Header)), ;);
aMessage.Read(aMessage.GetOffset(), sizeof(header), &header);
aMessage.MoveOffset(sizeof(header));
// discard if not solicit type
VerifyOrExit((header.GetType() == kTypeSolicit), ;);
ProcessSolicit(aMessage, dst, header.GetTransactionId());
exit:
{}
}
void Dhcp6Server::ProcessSolicit(Message &aMessage, otIp6Address &aDst, uint8_t *aTransactionId)
{
IaNa iana;
ClientIdentifier clientIdentifier;
uint16_t optionOffset;
uint16_t offset = aMessage.GetOffset();
uint16_t length = aMessage.GetLength() - aMessage.GetOffset();
// Client Identifier (discard if not present)
VerifyOrExit((optionOffset = FindOption(aMessage, offset, length, kOptionClientIdentifier)) > 0, ;);
SuccessOrExit(ProcessClientIdentifier(aMessage, optionOffset, clientIdentifier));
// Server Identifier (assuming Rapid Commit, discard if present)
VerifyOrExit(FindOption(aMessage, offset, length, kOptionServerIdentifier) == 0, ;);
// Rapid Commit (assuming Rapid Commit, discard if not present)
VerifyOrExit(FindOption(aMessage, offset, length, kOptionRapidCommit) > 0, ;);
// Elapsed Time if present
if ((optionOffset = FindOption(aMessage, offset, length, kOptionElapsedTime)) > 0)
{
SuccessOrExit(ProcessElapsedTime(aMessage, optionOffset));
}
// IA_NA (discard if not present)
VerifyOrExit((optionOffset = FindOption(aMessage, offset, length, kOptionIaNa)) > 0, ;);
SuccessOrExit(ProcessIaNa(aMessage, optionOffset, iana));
SuccessOrExit(SendReply(aDst, aTransactionId, clientIdentifier, iana));
exit:
{}
}
uint16_t Dhcp6Server::FindOption(Message &aMessage, uint16_t aOffset, uint16_t aLength, Code aCode)
{
uint16_t end = aOffset + aLength;
while (aOffset <= end)
{
Dhcp6Option option;
aMessage.Read(aOffset, sizeof(option), &option);
if (option.GetCode() == aCode)
{
return aOffset;
}
aOffset += sizeof(option) + option.GetLength();
}
return 0;
}
ThreadError Dhcp6Server::ProcessClientIdentifier(Message &aMessage, uint16_t aOffset, ClientIdentifier &aClient)
{
ThreadError error = kThreadError_None;
VerifyOrExit(((aMessage.Read(aOffset, sizeof(aClient), &aClient) == sizeof(aClient)) &&
(aClient.GetLength() == (sizeof(aClient) - sizeof(Dhcp6Option))) &&
(aClient.GetDuidType() == kDuidLL) &&
(aClient.GetDuidHardwareType() == kHardwareTypeEui64)),
error = kThreadError_Parse);
exit:
return error;
}
ThreadError Dhcp6Server::ProcessElapsedTime(Message &aMessage, uint16_t aOffset)
{
ThreadError error = kThreadError_None;
ElapsedTime option;
VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) &&
(option.GetLength() == ((sizeof(option) - sizeof(Dhcp6Option))))),
error = kThreadError_Parse);
exit:
return error;
}
ThreadError Dhcp6Server::ProcessIaNa(Message &aMessage, uint16_t aOffset, IaNa &aIaNa)
{
ThreadError error = kThreadError_None;
uint16_t optionOffset;
int length;
VerifyOrExit((aMessage.Read(aOffset, sizeof(aIaNa), &aIaNa) == sizeof(aIaNa)), error = kThreadError_Parse);
aOffset += sizeof(aIaNa);
length = aIaNa.GetLength() + sizeof(Dhcp6Option) - sizeof(IaNa);
mPrefixAgentsMask = 0;
while (length > 0)
{
VerifyOrExit((optionOffset = FindOption(aMessage, aOffset, length, kOptionIaAddress)) > 0, ;);
SuccessOrExit(error = ProcessIaAddress(aMessage, optionOffset));
length -= ((optionOffset - aOffset) + sizeof(IaAddress));
aOffset = optionOffset + sizeof(IaAddress);
}
exit:
return error;
}
ThreadError Dhcp6Server::ProcessIaAddress(Message &aMessage, uint16_t aOffset)
{
ThreadError error = kThreadError_None;
otIp6Prefix *prefix = NULL;
IaAddress option;
VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) &&
option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option))),
error = kThreadError_Parse);
// mask matching prefix
for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
prefix = mPrefixAgents[i].GetPrefix();
if (prefix->mLength == 0)
{
continue;
}
if (otIp6PrefixMatch(option.GetAddress(), &(prefix->mPrefix)) >= prefix->mLength)
{
mPrefixAgentsMask |= (1 << i);;
break;
}
}
exit:
return error;
}
ThreadError Dhcp6Server::SendReply(otIp6Address &aDst, uint8_t *aTransactionId, ClientIdentifier &aClient, IaNa &aIaNa)
{
ThreadError error = kThreadError_None;
Ip6::MessageInfo messageInfo;
Message *message;
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
SuccessOrExit(error = AppendHeader(*message, aTransactionId));
SuccessOrExit(error = AppendServerIdentifier(*message));
SuccessOrExit(error = AppendClientIdentifier(*message, aClient));
SuccessOrExit(error = AppendIaNa(*message, aIaNa));
SuccessOrExit(error = AppendStatusCode(*message, kStatusSuccess));
SuccessOrExit(error = AppendIaAddress(*message, aClient));
SuccessOrExit(error = AppendRapidCommit(*message));
memset(&messageInfo, 0, sizeof(messageInfo));
memcpy(&messageInfo.GetPeerAddr().mFields.m8, &aDst, sizeof(otIp6Address));
messageInfo.mPeerPort = kDhcpClientPort;
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
exit:
if (message != NULL && error != kThreadError_None)
{
message->Free();
}
return error;
}
ThreadError Dhcp6Server::AppendHeader(Message &aMessage, uint8_t *aTransactionId)
{
Dhcp6Header header;
header.Init();
header.SetType(kTypeReply);
header.SetTransactionId(aTransactionId);
return aMessage.Append(&header, sizeof(header));
}
ThreadError Dhcp6Server::AppendClientIdentifier(Message &aMessage, ClientIdentifier &aClient)
{
return aMessage.Append(&aClient, sizeof(aClient));
}
ThreadError Dhcp6Server::AppendServerIdentifier(Message &aMessage)
{
ThreadError error = kThreadError_None;
ServerIdentifier option;
option.Init();
option.SetDuidType(kDuidLL);
option.SetDuidHardwareType(kHardwareTypeEui64);
option.SetDuidLinkLayerAddress(mMac.GetExtAddress());
SuccessOrExit(error = aMessage.Append(&option, sizeof(option)));
exit:
return error;
}
ThreadError Dhcp6Server::AppendIaNa(Message &aMessage, IaNa &aIaNa)
{
ThreadError error = kThreadError_None;
uint16_t length = 0;
if (mPrefixAgentsMask)
{
for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
if ((mPrefixAgentsMask & (1 << i)))
{
length += sizeof(IaAddress);
}
}
}
else
{
length += sizeof(IaAddress) * mPrefixAgentsCount;
}
length += sizeof(IaNa) + sizeof(StatusCode) - sizeof(Dhcp6Option);
aIaNa.SetLength(length);
aIaNa.SetT1(kDefaultIaNaT1);
aIaNa.SetT2(kDefaultIaNaT2);
SuccessOrExit(error = aMessage.Append(&aIaNa, sizeof(IaNa)));
exit:
return error;
}
ThreadError Dhcp6Server::AppendStatusCode(Message &aMessage, Status aStatus)
{
StatusCode option;
option.Init();
option.SetStatusCode(aStatus);
return aMessage.Append(&option, sizeof(option));
}
ThreadError Dhcp6Server::AppendIaAddress(Message &aMessage, ClientIdentifier &aClient)
{
ThreadError error = kThreadError_None;
otIp6Prefix *prefix = NULL;
// if specified, only apply specified prefixes
if (mPrefixAgentsMask)
{
for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
if (mPrefixAgentsMask & (1 << i))
{
prefix = mPrefixAgents[i].GetPrefix();
SuccessOrExit(error = AddIaAddress(aMessage, *prefix, aClient));
}
}
}
else // if not specified, apply all configured prefixes
{
for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
{
prefix = mPrefixAgents[i].GetPrefix();
if (prefix->mLength == 0)
{
continue;
}
SuccessOrExit(error = AddIaAddress(aMessage, *prefix, aClient));
}
}
exit:
return error;
}
ThreadError Dhcp6Server::AddIaAddress(Message &aMessage, otIp6Prefix &aIp6Prefix, ClientIdentifier &aClient)
{
ThreadError error = kThreadError_None;
IaAddress option;
option.Init();
memcpy((option.GetAddress()->mFields.m8), &(aIp6Prefix.mPrefix), 8);
memcpy(&(option.GetAddress()->mFields.m8[8]), aClient.GetDuidLinkLayerAddress(), sizeof(Mac::ExtAddress));
option.SetPreferredLifetime(kDefaultIaAddressPreferredLifetime);
option.SetValidLifetime(kDefaultIaAddressValidLifetime);
SuccessOrExit(error = aMessage.Append(&option, sizeof(option)));
exit:
return error;
}
ThreadError Dhcp6Server::AppendRapidCommit(Message &aMessage)
{
RapidCommit option;
option.Init();
return aMessage.Append(&option, sizeof(option));
}
} // namespace Dhcp6
} // namespace Thread
+168
View File
@@ -0,0 +1,168 @@
/*
* 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 DHCPv6 Server.
*/
#ifndef DHCP6_SERVER_HPP_
#define DHCP6_SERVER_HPP_
#include <openthread-types.h>
#include <mac/mac_frame.hpp>
#include <mac/mac.hpp>
#include <net/dhcp6.hpp>
#include <net/udp6.hpp>
#include <thread/network_data_leader.hpp>
namespace Thread {
class ThreadNetif;
namespace NetworkData { class Leader; }
namespace Dhcp6 {
/**
* @addtogroup core-dhcp6
*
* @brief
* This module includes definitions for DHCPv6 Server.
*
* @{
*
*/
/**
* DHCPv6 default constant
*
*/
enum
{
kDefaultIaNaT1 = 0xffffffff,
kDefaultIaNaT2 = 0xffffffff,
kDefaultIaAddressPreferredLifetime = 0xffffffff,
kDefaultIaAddressValidLifetime = 0xffffffff,
};
/**
* This class implements prefix agent.
*
*/
OT_TOOL_PACKED_BEGIN
class PrefixAgent
{
public:
/**
* This method returns the reference to the IPv6 prefix.
*
* @returns A reference to the IPv6 prefix.
*
*/
otIp6Prefix *GetPrefix(void) { return &mIp6Prefix; }
/**
* This method sets the IPv6 prefix.
*
* @param[in] aIp6Prefix The reference to the IPv6 prefix to set.
*
*/
void SetPrefix(otIp6Prefix &aIp6Prefix) { memcpy(&mIp6Prefix, &aIp6Prefix, sizeof(otIp6Prefix)); }
private:
otIp6Prefix mIp6Prefix; ///< prefix
} OT_TOOL_PACKED_END;
class Dhcp6Server
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aThreadNetif A reference to the Thread network interface.
*
*/
explicit Dhcp6Server(ThreadNetif &aThreadNetif);
/**
* This method updates DHCP Agents and DHCP Alocs.
*
*/
ThreadError UpdateService();
private:
ThreadError Start(void);
ThreadError Stop(void);
ThreadError AddPrefixAgent(otIp6Prefix &aIp6Prefix);
ThreadError RemovePrefixAgent(const uint8_t *aIp6Address);
ThreadError AppendHeader(Message &aMessage, uint8_t *aTransactionId);
ThreadError AppendClientIdentifier(Message &aMessage, ClientIdentifier &aClient);
ThreadError AppendServerIdentifier(Message &aMessage);
ThreadError AppendIaNa(Message &aMessage, IaNa &aIaNa);
ThreadError AppendStatusCode(Message &aMessage, Status aStatusCode);
ThreadError AppendIaAddress(Message &aMessage, ClientIdentifier &aClient);
ThreadError AppendRapidCommit(Message &aMessage);
ThreadError AppendVendorSpecificInformation(Message &aMessage);
ThreadError AddIaAddress(Message &aMessage, otIp6Prefix &aIp6Prefix, ClientIdentifier &aClient);
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessSolicit(Message &aMessage, otIp6Address &aDst, uint8_t *aTransactionId);
uint16_t FindOption(Message &aMessage, uint16_t aOffset, uint16_t aLength, Code aCode);
ThreadError ProcessClientIdentifier(Message &aMessage, uint16_t aOffset, ClientIdentifier &aClient);
ThreadError ProcessIaNa(Message &aMessage, uint16_t aOffset, IaNa &aIaNa);
ThreadError ProcessIaAddress(Message &aMessage, uint16_t aOffset);
ThreadError ProcessElapsedTime(Message &aMessage, uint16_t aOffset);
ThreadError SendReply(otIp6Address &aDst, uint8_t *aTransactionId, ClientIdentifier &aClientIdentifier, IaNa &aIaNa);
Ip6::UdpSocket mSocket;
Mac::Mac &mMac;
Mle::MleRouter &mMle;
NetworkData::Leader &mNetworkDataLeader;
ThreadNetif &mNetif;
Ip6::NetifUnicastAddress mAgentsAloc[OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES];
PrefixAgent mPrefixAgents[OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES];
uint8_t mPrefixAgentsMask;
uint8_t mPrefixAgentsCount;
};
} // namespace Dhcp6
} // namespace Thread
#endif // DHCP6_SERVER_HPP_
+20
View File
@@ -342,4 +342,24 @@
*/
#define OPENTHREAD_CONFIG_LOG_NETDIAG
/**
* @def OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES
*
* The number of dhcp prefixes.
*
*/
#ifndef OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES
#define OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES 4
#endif // OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES
/**
* @def OPENTHREAD_CONFIG_NUM_SLAAC_ADDRESSES
*
* The number of autoconfigured SLAAC addresses.
*
*/
#ifndef OPENTHREAD_CONFIG_NUM_SLAAC_ADDRESSES
#define OPENTHREAD_CONFIG_NUM_SLAAC_ADDRESSES 4
#endif // OPENTHREAD_CONFIG_NUM_SLAAC_ADDRESSES
#endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_
+8 -1
View File
@@ -56,7 +56,7 @@
#include <platform/misc.h>
#include <thread/thread_netif.hpp>
#include <thread/thread_uris.hpp>
#include <utils/global_address.hpp>
#include <utils/slaac_address.hpp>
#include <openthread-instance.h>
#include <coap/coap_header.hpp>
#include <coap/coap_client.hpp>
@@ -922,6 +922,13 @@ ThreadError otRemoveUnicastAddress(otInstance *aInstance, const otIp6Address *ad
return aInstance->mThreadNetif.RemoveExternalUnicastAddress(*static_cast<const Ip6::Address *>(address));
}
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
void otDhcp6ClientUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses, void *aContext)
{
aInstance->mThreadNetif.GetDhcp6Client().UpdateAddresses(aInstance, aAddresses, aNumAddresses, aContext);
}
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
void otSlaacUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses,
otSlaacIidCreate aIidCreate, void *aContext)
{
+1 -1
View File
@@ -107,7 +107,7 @@ public:
* @param[in] aBufferLen The char buffer length.
*
* @retval kThreadError_None Successfully formed the string in the given char buffer.
* @retval kThreadError_NoBuf The string representation of the average value could not fit in the given buffer.
* @retval kThreadError_NoBufs The string representation of the average value could not fit in the given buffer.
*
*/
ThreadError GetAverageRssAsString(char *aCharBuffer, size_t aBufferLen) const;
+25
View File
@@ -46,6 +46,7 @@
#include <platform/random.h>
#include <thread/mesh_forwarder.hpp>
#include <thread/mle_router.hpp>
#include <thread/mle.hpp>
#include <thread/thread_netif.hpp>
using Thread::Encoding::BigEndian::HostSwap16;
@@ -663,6 +664,30 @@ ThreadError MeshForwarder::UpdateIp6Route(Message &aMessage)
{
mMeshDest = mMle.GetRloc16(mMle.GetLeaderId());
}
#if OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT
else if ((aloc16 & Mle::kAloc16DhcpAgentMask) != 0)
{
uint16_t agentRloc16;
uint8_t routerId;
VerifyOrExit((mNetworkData.GetRlocByContextId(static_cast<uint8_t>(aloc16 & Mle::kAloc16DhcpAgentMask),
agentRloc16) == kThreadError_None), error = kThreadError_Drop);
routerId = mMle.GetRouterId(agentRloc16);
// if agent is active router or the child of the device
if ((mMle.IsActiveRouter(agentRloc16)) || (mMle.GetRloc16(routerId) == mMle.GetRloc16()))
{
mMeshDest = agentRloc16;
}
else
{
// use the parent of the ED Agent as Dest
mMeshDest = mMle.GetRloc16(routerId);
}
}
#endif // OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT
else
{
// TODO: support ALOC for DHCPv6 Agent, Service, Commissioner, Neighbor Discovery Agent
+3 -2
View File
@@ -111,8 +111,9 @@ enum AlocAllocation
{
kAloc16Mask = 0xfc,
kAloc16Leader = 0xfc00,
kAloc16DHCPv6AgentStart = 0xfc01,
kAloc16DHCPv6AgentEnd = 0xfc0f,
kAloc16DhcpAgentStart = 0xfc01,
kAloc16DhcpAgentEnd = 0xfc0f,
kAloc16DhcpAgentMask = 0x03ff,
kAloc16ServiceStart = 0xfc10,
kAloc16ServiceEnd = 0xfc2f,
kAloc16CommissionerStart = 0xfc30,
+2 -1
View File
@@ -125,6 +125,7 @@ ThreadError NetworkData::GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, u
aConfig->mDefaultRoute = borderRouterEntry->IsDefaultRoute();
aConfig->mOnMesh = borderRouterEntry->IsOnMesh();
aConfig->mStable = cur->IsStable();
aConfig->mRloc16 = borderRouterEntry->GetRloc();
*aIterator = static_cast<otNetworkDataIterator>(reinterpret_cast<uint8_t *>(cur->GetNext()) - mTlvs);
@@ -208,7 +209,7 @@ bool NetworkData::ContainsOnMeshPrefixes(NetworkData &aCompare, uint16_t aRloc16
while ((error = GetNextOnMeshPrefix(&innerIterator, aRloc16, &innerConfig)) == kThreadError_None)
{
if (memcmp(&outerConfig, &innerConfig, sizeof(outerConfig)) == 0)
if (memcmp(&outerConfig, &innerConfig, (sizeof(outerConfig) - sizeof(outerConfig.mRloc16))) == 0)
{
break;
}
+28
View File
@@ -47,6 +47,7 @@
#include <thread/thread_netif.hpp>
#include <thread/thread_tlvs.hpp>
#include <thread/thread_uris.hpp>
#include <thread/lowpan.hpp>
using Thread::Encoding::BigEndian::HostSwap16;
@@ -222,6 +223,33 @@ exit:
return error;
}
#if OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT
ThreadError Leader::GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16)
{
ThreadError error = kThreadError_NotFound;
Lowpan::Context lowpanContext;
if ((GetContext(aContextId, lowpanContext)) == kThreadError_None)
{
otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
otBorderRouterConfig config;
while (GetNextOnMeshPrefix(&iterator, &config) == kThreadError_None)
{
if (otIp6PrefixMatch(&(config.mPrefix.mPrefix),
reinterpret_cast<const otIp6Address *>(lowpanContext.mPrefix)) >= config.mPrefix.mLength)
{
aRloc16 = config.mRloc16;
ExitNow(error = kThreadError_None);
}
}
}
exit:
return error;
}
#endif // OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT
bool Leader::IsOnMesh(const Ip6::Address &aAddress)
{
PrefixTlv *prefix;
+14 -1
View File
@@ -241,6 +241,20 @@ public:
*/
ThreadError SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength);
#if OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT
/**
* This method gets the Rloc of Dhcp Agent of speficified contextId.
*
* @param[in] aContextId A pointer to the Commissioning Data value.
* @param[out] aRloc16 The reference of which for output the Rloc16.
*
* @retval kThreadError_None Successfully get the Rloc of Dhcp Agent.
* @retval kThreadError_NotFound The specified @p aContextId could not be found.
*
*/
ThreadError GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16);
#endif // OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT
private:
static void HandleServerData(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
@@ -293,7 +307,6 @@ private:
uint8_t *aTlvs, uint8_t aLength);
void SendCommissioningSetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
MeshCoP::StateTlv::State aState);
/**
* Thread Specification Constants
*
+6
View File
@@ -58,6 +58,12 @@ ThreadNetif::ThreadNetif(Ip6::Ip6 &aIp6):
mCoapServer(aIp6.mUdp, kCoapUdpPort),
mCoapClient(*this),
mAddressResolver(*this),
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
mDhcp6Client(*this),
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
#if OPENTHREAD_ENABLE_DHCP6_SERVER
mDhcp6Server(*this),
#endif // OPENTHREAD_ENABLE_DHCP6_SERVER
mActiveDataset(*this),
mPendingDataset(*this),
mKeyManager(*this),
+29
View File
@@ -47,6 +47,9 @@
#include <mac/mac.hpp>
#include <meshcop/joiner_router.hpp>
#include <meshcop/leader.hpp>
#include <net/dhcp6.hpp>
#include <net/dhcp6_client.hpp>
#include <net/dhcp6_server.hpp>
#include <net/ip6_filter.hpp>
#include <net/netif.hpp>
#include <thread/address_resolver.hpp>
@@ -163,6 +166,26 @@ public:
*/
NetworkDiagnostic::NetworkDiagnostic &GetNetworkDiagnostic(void) { return mNetworkDiagnostic; }
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
/**
* This method returns a pointer to the dhcp client object.
*
* @returns A reference to the dhcp client object.
*
*/
Dhcp6::Dhcp6Client &GetDhcp6Client(void) { return mDhcp6Client; }
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
#if OPENTHREAD_ENABLE_DHCP6_SERVER
/**
* This method returns a pointer to the dhcp server object.
*
* @returns A reference to the the dhcp server object.
*
*/
Dhcp6::Dhcp6Server &GetDhcp6Server(void) { return mDhcp6Server; }
#endif // OPENTHREAD_ENABLE_DHCP6_SERVER
/**
* This method returns a reference to the CoAP server object.
*
@@ -277,6 +300,12 @@ private:
Coap::Server mCoapServer;
Coap::Client mCoapClient;
AddressResolver mAddressResolver;
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
Dhcp6::Dhcp6Client mDhcp6Client;
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
#if OPENTHREAD_ENABLE_DHCP6_SERVER
Dhcp6::Dhcp6Server mDhcp6Server;
#endif // OPENTHREAD_ENABLE_DHCP6_SERVER
MeshCoP::ActiveDataset mActiveDataset;
MeshCoP::PendingDataset mPendingDataset;
Ip6::Filter mIp6Filter;
@@ -44,7 +44,7 @@
#include <crypto/sha256.hpp>
#include <mac/mac.hpp>
#include <net/ip6_address.hpp>
#include <utils/global_address.hpp>
#include <utils/slaac_address.hpp>
#include <string.h>
@@ -31,8 +31,8 @@
* This file includes definitions for Thread global IPv6 address configuration with SLAAC.
*/
#ifndef GLOBAL_ADDRESS_HPP_
#define GLOBAL_ADDRESS_HPP_
#ifndef SLAAC_ADDRESS_HPP_
#define SLAAC_ADDRESS_HPP_
#include <openthread-types.h>
#include <platform/random.h>
@@ -41,7 +41,7 @@ namespace Thread {
namespace Utils {
/**
* @addtogroup core-global-address
* @addtogroup core-slaac-address
*
* @brief
* This module includes definitions for Thread global IPv6 address configuration with SLAAC.
@@ -158,5 +158,5 @@ private:
} // namespace Slaac
} // namespace Thread
#endif // GLOBAL_ADDRESS_HPP_
#endif // SLAAC_ADDRESS_HPP_
+3
View File
@@ -60,6 +60,7 @@ EXTRA_DIST = \
thread-cert/Cert_5_3_06b_RouterIdMask.py \
thread-cert/Cert_5_3_07_DuplicateAddress.py \
thread-cert/Cert_5_3_08_ChildAddressSet.py \
thread-cert/Cert_5_3_09_AddressQuery.py \
thread-cert/Cert_5_3_10_AddressQuery.py \
thread-cert/Cert_5_5_01_LeaderReset.py \
thread-cert/Cert_5_5_02_LeaderReboot.py \
@@ -178,6 +179,7 @@ check_SCRIPTS += \
thread-cert/Cert_5_3_06b_RouterIdMask.py \
thread-cert/Cert_5_3_07_DuplicateAddress.py \
thread-cert/Cert_5_3_08_ChildAddressSet.py \
thread-cert/Cert_5_3_09_AddressQuery.py \
thread-cert/Cert_5_3_10_AddressQuery.py \
thread-cert/Cert_5_5_01_LeaderReset.py \
thread-cert/Cert_5_5_02_LeaderReboot.py \
@@ -268,6 +270,7 @@ TESTS = \
$(NULL)
XFAIL_NCP_TESTS = \
thread-cert/Cert_5_3_09_AddressQuery.py \
thread-cert/Cert_8_1_01_Commissioning.py \
thread-cert/Cert_8_1_02_Commissioning.py \
thread-cert/Cert_8_2_01_JoinerRouter.py \
+149
View File
@@ -0,0 +1,149 @@
#!/usr/bin/python
#
# 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.
#
import time
import unittest
import node
LEADER = 1
ROUTER1 = 2
ROUTER2 = 3
ROUTER3 = 4
SED1 = 5
class Cert_5_3_09_AddressQuery(unittest.TestCase):
def setUp(self):
self.nodes = {}
for i in range(1,6):
self.nodes[i] = node.Node(i)
self.nodes[LEADER].set_panid(0xface)
self.nodes[LEADER].set_mode('rsdn')
self.nodes[LEADER].add_whitelist(self.nodes[ROUTER1].get_addr64())
self.nodes[LEADER].add_whitelist(self.nodes[ROUTER2].get_addr64())
self.nodes[LEADER].add_whitelist(self.nodes[ROUTER3].get_addr64())
self.nodes[LEADER].enable_whitelist()
self.nodes[ROUTER1].set_panid(0xface)
self.nodes[ROUTER1].set_mode('rsdn')
self.nodes[ROUTER1].add_whitelist(self.nodes[LEADER].get_addr64())
self.nodes[ROUTER1].enable_whitelist()
self.nodes[ROUTER1].set_router_selection_jitter(1)
self.nodes[ROUTER2].set_panid(0xface)
self.nodes[ROUTER2].set_mode('rsdn')
self.nodes[ROUTER2].add_whitelist(self.nodes[LEADER].get_addr64())
self.nodes[ROUTER2].add_whitelist(self.nodes[SED1].get_addr64())
self.nodes[ROUTER2].enable_whitelist()
self.nodes[ROUTER2].set_router_selection_jitter(1)
self.nodes[ROUTER3].set_panid(0xface)
self.nodes[ROUTER3].set_mode('rsdn')
self.nodes[ROUTER3].add_whitelist(self.nodes[LEADER].get_addr64())
self.nodes[ROUTER3].add_whitelist(self.nodes[ROUTER2].get_addr64())
self.nodes[ROUTER3].enable_whitelist()
self.nodes[ROUTER3].set_router_selection_jitter(1)
self.nodes[SED1].set_panid(0xface)
self.nodes[SED1].set_mode('sn')
self.nodes[SED1].add_whitelist(self.nodes[ROUTER2].get_addr64())
self.nodes[SED1].set_timeout(3)
self.nodes[SED1].enable_whitelist()
def tearDown(self):
for node in list(self.nodes.values()):
node.stop()
del self.nodes
def test(self):
self.nodes[LEADER].start()
self.nodes[LEADER].set_state('leader')
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
self.nodes[LEADER].add_prefix('2001:2:0:1::/64', 'pdros')
self.nodes[LEADER].add_prefix('2001:2:0:2::/64', 'pdro')
self.nodes[LEADER].register_netdata()
self.nodes[ROUTER1].start()
time.sleep(5)
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
self.nodes[ROUTER2].start()
time.sleep(5)
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
self.nodes[ROUTER3].start()
time.sleep(5)
self.assertEqual(self.nodes[ROUTER3].get_state(), 'router')
self.nodes[SED1].start()
time.sleep(5)
self.assertEqual(self.nodes[SED1].get_state(), 'child')
# wait for sed got replied
time.sleep(10)
addrs = self.nodes[ROUTER3].get_addrs()
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
for addr in addrs:
if addr[0:4] != 'fe80':
self.assertTrue(self.nodes[SED1].ping(addr))
addrs = self.nodes[SED1].get_addrs()
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
for addr in addrs:
if addr[0:4] != 'fe80':
self.assertTrue(self.nodes[ROUTER1].ping(addr))
addrs = self.nodes[ROUTER3].get_addrs()
for addr in addrs:
if addr[0:4] != 'fe80':
self.assertTrue(self.nodes[SED1].ping(addr))
self.nodes[ROUTER3].stop()
time.sleep(300)
addrs = self.nodes[ROUTER3].get_addrs()
for addr in addrs:
if addr[0:4] != 'fe80':
self.assertFalse(self.nodes[SED1].ping(addr))
self.nodes[SED1].stop()
time.sleep(10)
addrs = self.nodes[SED1].get_addrs()
for addr in addrs:
if addr[0:4] != 'fe80':
self.assertFalse(self.nodes[ROUTER1].ping(addr))
if __name__ == '__main__':
unittest.main()