mirror of
https://github.com/espressif/openthread.git
synced 2026-08-31 06:19:54 +00:00
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:
+2
-2
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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}
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
@@ -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()
|
||||
Reference in New Issue
Block a user