diff --git a/src/core/config/dhcp6_client.h b/src/core/config/dhcp6_client.h index c80503422..9b50636e1 100644 --- a/src/core/config/dhcp6_client.h +++ b/src/core/config/dhcp6_client.h @@ -45,6 +45,16 @@ #define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_DHCP6_MULTICAST_SOLICIT + * + * Define to 1 to enable DHCPv6 multicast solicit. + * + */ +#ifndef OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT +#define OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT 0 +#endif + /** * @def OPENTHREAD_CONFIG_DHCP6_CLIENT_NUM_PREFIXES * diff --git a/src/core/config/openthread-core-config-check.h b/src/core/config/openthread-core-config-check.h index 94f941f91..86bb5bafc 100644 --- a/src/core/config/openthread-core-config-check.h +++ b/src/core/config/openthread-core-config-check.h @@ -38,6 +38,10 @@ #error "OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE and OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE must not both be set." #endif +#if OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT && !OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE +#error "OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT requires OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE to be also set." +#endif + /* * Removed or replaced OPENTHREAD_CONFIG options. * diff --git a/src/core/net/dhcp6.hpp b/src/core/net/dhcp6.hpp index 5251cfd4a..875e766e6 100644 --- a/src/core/net/dhcp6.hpp +++ b/src/core/net/dhcp6.hpp @@ -61,11 +61,13 @@ using ot::Encoding::BigEndian::HostSwap32; */ enum { - kDhcpClientPort = 546, - kDhcpServerPort = 547, - kTransactionIdSize = 3, - kLinkLayerAddressLen = 8, - kHardwareTypeEui64 = 27, + kDhcpClientPort = 546, + kDhcpServerPort = 547, + kTransactionIdSize = 3, + kLinkLayerAddressLen = 8, + kHardwareTypeEui64 = 27, + kHardwareTypeEthernet = 1, + kLinkLayerAddressPlusLen = 6, }; /** diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp index da20f5dfe..a10e4c867 100644 --- a/src/core/net/dhcp6_client.cpp +++ b/src/core/net/dhcp6_client.cpp @@ -275,12 +275,17 @@ otError Dhcp6Client::Solicit(uint16_t aRloc16) SuccessOrExit(error = AppendIaAddress(*message, aRloc16)); SuccessOrExit(error = AppendRapidCommit(*message)); +#if OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT + messageInfo.GetPeerAddr().mFields.m16[0] = HostSwap16(0xff03); + messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(0x0002); +#else memcpy(messageInfo.GetPeerAddr().mFields.m8, Get().GetMeshLocalPrefix().m8, sizeof(otMeshLocalPrefix)); 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); +#endif messageInfo.SetSockAddr(Get().GetMeshLocal16()); messageInfo.mPeerPort = kDhcpServerPort; @@ -432,6 +437,11 @@ void Dhcp6Client::ProcessReply(Message &aMessage) uint16_t length = aMessage.GetLength() - aMessage.GetOffset(); uint16_t optionOffset; + if ((optionOffset = FindOption(aMessage, offset, length, kOptionStatusCode)) > 0) + { + SuccessOrExit(ProcessStatusCode(aMessage, optionOffset)); + } + // Server Identifier VerifyOrExit((optionOffset = FindOption(aMessage, offset, length, kOptionServerIdentifier)) > 0); SuccessOrExit(ProcessServerIdentifier(aMessage, optionOffset)); @@ -480,9 +490,10 @@ otError Dhcp6Client::ProcessServerIdentifier(Message &aMessage, uint16_t aOffset otError error = OT_ERROR_NONE; ServerIdentifier option; - VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) && - (option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option))) && (option.GetDuidType() == kDuidLL) && - (option.GetDuidHardwareType() == kHardwareTypeEui64)), + VerifyOrExit((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option))); + VerifyOrExit(((option.GetDuidType() == kDuidLLT) && (option.GetDuidHardwareType() == kHardwareTypeEthernet)) || + ((option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option))) && + (option.GetDuidType() == kDuidLL) && (option.GetDuidHardwareType() == kHardwareTypeEui64)), error = OT_ERROR_PARSE); exit: return error; @@ -546,8 +557,8 @@ otError Dhcp6Client::ProcessStatusCode(Message &aMessage, uint16_t aOffset) otError error = OT_ERROR_NONE; StatusCode option; - VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) && - (option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option))) && + VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) >= sizeof(option)) && + (option.GetLength() >= (sizeof(option) - sizeof(Dhcp6Option))) && (option.GetStatusCode() == kStatusSuccess)), error = OT_ERROR_PARSE);