[mle] fix the issue when the number of registered addresses exceeds the parent's capacity (#2518)

This commit is contained in:
rongli
2018-01-31 16:47:36 +00:00
committed by Jonathan Hui
parent 050cf9074f
commit 9190aa21c4
3 changed files with 54 additions and 94 deletions
+53 -39
View File
@@ -2081,46 +2081,62 @@ exit:
return OT_ERROR_NONE;
}
otError MleRouter::UpdateChildAddresses(const AddressRegistrationTlv &aTlv, Child &aChild)
otError MleRouter::UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, Child &aChild)
{
const AddressRegistrationEntry *entry;
otError error = OT_ERROR_NONE;
AddressRegistrationEntry entry;
Ip6::Address address;
Lowpan::Context context;
uint8_t count;
Tlv tlv;
uint8_t registeredCount = 0;
uint8_t storedCount = 0;
uint16_t offset = 0;
uint16_t end = 0;
char stringBuffer[Ip6::Address::kIp6AddressStringSize];
VerifyOrExit(aMessage.Read(aOffset, sizeof(tlv), &tlv) == sizeof(tlv), error = OT_ERROR_PARSE);
VerifyOrExit(tlv.GetLength() <= (aMessage.GetLength() - aOffset - sizeof(tlv)), error = OT_ERROR_PARSE);
offset = aOffset + sizeof(tlv);
end = offset + tlv.GetLength();
aChild.ClearIp6Addresses();
for (count = 0; ; count++)
while (offset < end)
{
otError error = OT_ERROR_NONE;
uint8_t len;
if ((entry = aTlv.GetAddressEntry(count)) == NULL)
{
break;
}
// read out the control field
VerifyOrExit(aMessage.Read(offset, 1, &entry) == 1, error = OT_ERROR_PARSE);
if (entry->IsCompressed())
len = entry.GetLength();
VerifyOrExit(aMessage.Read(offset, len, &entry) == len, error = OT_ERROR_PARSE);
offset += len;
if (entry.IsCompressed())
{
// xxx check if context id exists
GetNetif().GetNetworkDataLeader().GetContext(entry->GetContextId(), context);
GetNetif().GetNetworkDataLeader().GetContext(entry.GetContextId(), context);
memcpy(&address, context.mPrefix, BitVectorBytes(context.mPrefixLength));
address.SetIid(entry->GetIid());
address.SetIid(entry.GetIid());
}
else
{
address = *entry->GetIp6Address();
address = *entry.GetIp6Address();
}
registeredCount++;
// We try to accept/add as many IPv6 addresses as possible.
// "Child ID/Update Response" will indicate the accepted
// addresses.
error = aChild.AddIp6Address(GetInstance(), address);
if (error == OT_ERROR_NONE)
{
otLogInfoMle(GetInstance(), "Child 0x%04x IPv6 address[%d]=%s", aChild.GetRloc16(), count,
storedCount++;
otLogInfoMle(GetInstance(), "Child 0x%04x IPv6 address[%d]=%s", aChild.GetRloc16(), storedCount,
address.ToString(stringBuffer, sizeof(stringBuffer)));
}
else
@@ -2158,19 +2174,24 @@ otError MleRouter::UpdateChildAddresses(const AddressRegistrationTlv &aTlv, Chil
}
}
if (count == 0)
if (registeredCount == 0)
{
otLogInfoMle(GetInstance(), "Child 0x%04x has no registered IPv6 address", aChild.GetRloc16());
}
else
{
otLogInfoMle(GetInstance(), "Child 0x%04x has %d registered IPv6 address%s", aChild.GetRloc16(), count,
(count == 1) ? "" : "es");
otLogInfoMle(GetInstance(), "Child 0x%04x has %d registered IPv6 address%s, %d address%s stored",
aChild.GetRloc16(), registeredCount, (registeredCount == 1) ? "" : "es",
storedCount, (storedCount == 1) ? "" : "es");
}
error = OT_ERROR_NONE;
exit:
OT_UNUSED_VARIABLE(stringBuffer);
return OT_ERROR_NONE;
return error;
}
otError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
@@ -2185,12 +2206,12 @@ otError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6::Mess
MleFrameCounterTlv mleFrameCounter;
ModeTlv mode;
TimeoutTlv timeout;
AddressRegistrationTlv address;
TlvRequestTlv tlvRequest;
ActiveTimestampTlv activeTimestamp;
PendingTimestampTlv pendingTimestamp;
Child *child;
uint8_t numTlvs;
uint16_t addressRegistrationOffset = 0;
LogMleMessage("Receive Child ID Request", aMessageInfo.GetPeerAddr());
@@ -2239,15 +2260,6 @@ otError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6::Mess
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kTimeout, sizeof(timeout), timeout));
VerifyOrExit(timeout.IsValid(), error = OT_ERROR_PARSE);
// Ip6 Address
address.SetLength(0);
if ((mode.GetMode() & ModeTlv::kModeFFD) == 0)
{
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kAddressRegistration, sizeof(address), address));
VerifyOrExit(address.IsValid(), error = OT_ERROR_PARSE);
}
// TLV Request
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest));
VerifyOrExit(tlvRequest.IsValid() && tlvRequest.GetLength() <= Child::kMaxRequestTlvs,
@@ -2269,6 +2281,12 @@ otError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6::Mess
VerifyOrExit(pendingTimestamp.IsValid(), error = OT_ERROR_PARSE);
}
if ((mode.GetMode() & ModeTlv::kModeFFD) == 0)
{
SuccessOrExit(error = Tlv::GetOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset));
SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
}
// Remove from router table
for (int i = 0; i <= kMaxRouterId; i++)
{
@@ -2306,8 +2324,6 @@ otError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6::Mess
child->SetNetworkDataVersion(mLeaderData.GetStableDataVersion());
}
UpdateChildAddresses(address, *child);
child->ClearRequestTlvs();
for (numTlvs = 0; numTlvs < tlvRequest.GetLength(); numTlvs++)
@@ -2358,13 +2374,13 @@ otError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const Ip6::
Mac::ExtAddress macAddr;
ModeTlv mode;
ChallengeTlv challenge;
AddressRegistrationTlv address;
LeaderDataTlv leaderData;
TimeoutTlv timeout;
Child *child;
TlvRequestTlv tlvRequest;
uint8_t tlvs[kMaxResponseTlvs];
uint8_t tlvslength = 0;
uint16_t addressRegistrationOffset = 0;
LogMleMessage("Receive Child Update Request from child", aMessageInfo.GetPeerAddr());
@@ -2408,10 +2424,9 @@ otError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const Ip6::
}
// Ip6 Address TLV
if (Tlv::GetTlv(aMessage, Tlv::kAddressRegistration, sizeof(address), address) == OT_ERROR_NONE)
if (Tlv::GetOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == OT_ERROR_NONE)
{
VerifyOrExit(address.IsValid(), error = OT_ERROR_PARSE);
UpdateChildAddresses(address, *child);
SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
tlvs[tlvslength++] = Tlv::kAddressRegistration;
}
@@ -2470,13 +2485,13 @@ otError MleRouter::HandleChildUpdateResponse(const Message &aMessage, const Ip6:
Mac::ExtAddress macAddr;
SourceAddressTlv sourceAddress;
TimeoutTlv timeout;
AddressRegistrationTlv address;
ResponseTlv response;
StatusTlv status;
LinkFrameCounterTlv linkFrameCounter;
MleFrameCounterTlv mleFrameCounter;
LeaderDataTlv leaderData;
Child *child;
uint16_t addressRegistrationOffset = 0;
// Find Child
aMessageInfo.GetPeerAddr().ToExtAddress(macAddr);
@@ -2546,10 +2561,9 @@ otError MleRouter::HandleChildUpdateResponse(const Message &aMessage, const Ip6:
}
// Ip6 Address
if (Tlv::GetTlv(aMessage, Tlv::kAddressRegistration, sizeof(address), address) == OT_ERROR_NONE)
if (Tlv::GetOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == OT_ERROR_NONE)
{
VerifyOrExit(address.IsValid(), error = OT_ERROR_PARSE);
UpdateChildAddresses(address, *child);
SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
}
// Leader Data
+1 -1
View File
@@ -835,7 +835,7 @@ private:
otError SetStateLeader(uint16_t aRloc16);
void StopLeader(void);
void SynchronizeChildNetworkData(void);
otError UpdateChildAddresses(const AddressRegistrationTlv &aTlv, Child &aChild);
otError UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, Child &aChild);
void UpdateRoutes(const RouteTlv &aTlv, uint8_t aRouterId);
static void HandleAddressSolicitResponse(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
-54
View File
@@ -1415,60 +1415,6 @@ private:
} OT_TOOL_PACKED_FIELD;
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class AddressRegistrationTlv: public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void) { SetType(kAddressRegistration); SetLength(sizeof(*this) - sizeof(Tlv)); }
/**
* This method indicates whether or not the TLV appears to be well-formed.
*
* @retval TRUE If the TLV appears to be well-formed.
* @retval FALSE If the TLV does not appear to be well-formed.
*
*/
bool IsValid(void) const { return GetLength() <= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns a pointer to the i'th Address Entry.
*
* @param[in] aIndex The index.
*
* @returns A pointer to the i'th Address Entry.
*
*/
const AddressRegistrationEntry *GetAddressEntry(uint8_t aIndex) const {
const AddressRegistrationEntry *entry = NULL;
const uint8_t *cur = reinterpret_cast<const uint8_t *>(mAddresses);
const uint8_t *end = cur + GetLength();
while (cur < end) {
entry = reinterpret_cast<const AddressRegistrationEntry *>(cur);
if (aIndex == 0) {
break;
}
cur += entry->GetLength();
aIndex--;
}
return (cur < end) ? entry : NULL;
}
private:
AddressRegistrationEntry mAddresses[OPENTHREAD_CONFIG_IP_ADDRS_PER_CHILD];
} OT_TOOL_PACKED_END;
/**
* This class implements Channel TLV generation and parsing.
*