ThreadError Local::AddHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, bool aStable) { PrefixTlv *prefixTlv; HasRouteTlv *hasRouteTlv; RemoveHasRoutePrefix(aPrefix, aPrefixLength); prefixTlv = reinterpret_cast<PrefixTlv *>(mTlvs + mLength); Insert(reinterpret_cast<uint8_t *>(prefixTlv), sizeof(PrefixTlv) + BitVectorBytes(aPrefixLength) + sizeof(HasRouteTlv) + sizeof(HasRouteEntry)); prefixTlv->Init(0, aPrefixLength, aPrefix); prefixTlv->SetSubTlvsLength(sizeof(HasRouteTlv) + sizeof(HasRouteEntry)); hasRouteTlv = reinterpret_cast<HasRouteTlv *>(prefixTlv->GetSubTlvs()); hasRouteTlv->Init(); hasRouteTlv->SetLength(hasRouteTlv->GetLength() + sizeof(HasRouteEntry)); hasRouteTlv->GetEntry(0)->Init(); hasRouteTlv->GetEntry(0)->SetPreference(aPrf); if (aStable) { prefixTlv->SetStable(); hasRouteTlv->SetStable(); } otDumpDebgNetData("add route done", mTlvs, mLength); return kThreadError_None; }
ThreadError Local::RemoveHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) { ThreadError error = kThreadError_None; PrefixTlv *tlv; VerifyOrExit((tlv = FindPrefix(aPrefix, aPrefixLength)) != NULL, error = kThreadError_Error); VerifyOrExit(FindHasRoute(*tlv) != NULL, error = kThreadError_Error); Remove(reinterpret_cast<uint8_t *>(tlv), sizeof(NetworkDataTlv) + tlv->GetLength()); exit: otDumpDebgNetData("remove done", mTlvs, mLength); return error; }
otError Local::RemoveService(uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength) { otError error = OT_ERROR_NONE; ServiceTlv *tlv; VerifyOrExit((tlv = FindService(aEnterpriseNumber, aServiceData, aServiceDataLength)) != NULL, error = OT_ERROR_NOT_FOUND); Remove(reinterpret_cast<uint8_t *>(tlv), sizeof(NetworkDataTlv) + tlv->GetLength()); ClearResubmitDelayTimer(); exit: otDumpDebgNetData("remove service done", mTlvs, mLength); return error; }
otError Local::RemoveHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) { otError error = OT_ERROR_NONE; PrefixTlv *tlv; VerifyOrExit((tlv = FindPrefix(aPrefix, aPrefixLength)) != NULL, error = OT_ERROR_NOT_FOUND); VerifyOrExit(FindHasRoute(*tlv) != NULL, error = OT_ERROR_NOT_FOUND); Remove(reinterpret_cast<uint8_t *>(tlv), sizeof(NetworkDataTlv) + tlv->GetLength()); ClearResubmitDelayTimer(); exit: otDumpDebgNetData("remove done", mTlvs, mLength); return error; }
otError Local::AddService(uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength, bool aServerStable, const uint8_t *aServerData, uint8_t aServerDataLength) { otError error = OT_ERROR_NONE; ServiceTlv *serviceTlv; ServerTlv * serverTlv; size_t serviceTlvLength = (sizeof(ServiceTlv) - sizeof(NetworkDataTlv)) + aServiceDataLength + sizeof(uint8_t) /*mServiceDataLength*/ + ServiceTlv::GetEnterpriseNumberFieldLength(aEnterpriseNumber) + aServerDataLength + sizeof(ServerTlv); RemoveService(aEnterpriseNumber, aServiceData, aServiceDataLength); VerifyOrExit(mLength + sizeof(NetworkDataTlv) + serviceTlvLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS); serviceTlv = reinterpret_cast<ServiceTlv *>(mTlvs + mLength); Insert(reinterpret_cast<uint8_t *>(serviceTlv), static_cast<uint8_t>(serviceTlvLength) + sizeof(NetworkDataTlv)); serviceTlv->Init(); serviceTlv->SetEnterpriseNumber(aEnterpriseNumber); serviceTlv->SetServiceID(0); serviceTlv->SetServiceData(aServiceData, aServiceDataLength); serviceTlv->SetLength(static_cast<uint8_t>(serviceTlvLength)); serverTlv = static_cast<ServerTlv *>(serviceTlv->GetSubTlvs()); serverTlv->Init(); // According to Thread spec 1.1.1, section 5.18.6 Service TLV: // "The Stable flag is set if any of the included sub-TLVs have their Stable flag set." // The meaning also seems to be 'if and only if'. if (aServerStable) { serviceTlv->SetStable(); serverTlv->SetStable(); } serverTlv->SetServer16(Get<Mle::MleRouter>().GetRloc16()); serverTlv->SetServerData(aServerData, aServerDataLength); ClearResubmitDelayTimer(); otDumpDebgNetData("add service done", mTlvs, mLength); exit: return error; }
otError Local::AddOnMeshPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, uint8_t aFlags, bool aStable) { otError error = OT_ERROR_NONE; uint8_t prefixLengthBytes = BitVectorBytes(aPrefixLength); uint8_t appendLength; PrefixTlv * prefixTlv; BorderRouterTlv *brTlv; VerifyOrExit(prefixLengthBytes <= sizeof(Ip6::Address), error = OT_ERROR_INVALID_ARGS); VerifyOrExit((aPrf == OT_ROUTE_PREFERENCE_LOW) || (aPrf == OT_ROUTE_PREFERENCE_MED) || (aPrf == OT_ROUTE_PREFERENCE_HIGH), error = OT_ERROR_INVALID_ARGS); VerifyOrExit(Ip6::Address::PrefixMatch(aPrefix, Get<Mle::MleRouter>().GetMeshLocalPrefix().m8, prefixLengthBytes) < Ip6::Address::kMeshLocalPrefixLength, error = OT_ERROR_INVALID_ARGS); RemoveOnMeshPrefix(aPrefix, aPrefixLength); appendLength = sizeof(PrefixTlv) + prefixLengthBytes + sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry); VerifyOrExit(mLength + appendLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS); prefixTlv = reinterpret_cast<PrefixTlv *>(mTlvs + mLength); Insert(reinterpret_cast<uint8_t *>(prefixTlv), appendLength); prefixTlv->Init(0, aPrefixLength, aPrefix); prefixTlv->SetSubTlvsLength(sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry)); brTlv = static_cast<BorderRouterTlv *>(prefixTlv->GetSubTlvs()); brTlv->Init(); brTlv->SetLength(brTlv->GetLength() + sizeof(BorderRouterEntry)); brTlv->GetEntry(0)->Init(); brTlv->GetEntry(0)->SetPreference(aPrf); brTlv->GetEntry(0)->SetFlags(aFlags); if (aStable) { prefixTlv->SetStable(); brTlv->SetStable(); } ClearResubmitDelayTimer(); otDumpDebgNetData("add prefix done", mTlvs, mLength); exit: return error; }
otError Local::AddHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, bool aStable) { otError error = OT_ERROR_NONE; uint8_t prefixLengthBytes = BitVectorBytes(aPrefixLength); PrefixTlv * prefixTlv; HasRouteTlv *hasRouteTlv; uint8_t appendLength; VerifyOrExit(prefixLengthBytes <= sizeof(Ip6::Address), error = OT_ERROR_INVALID_ARGS); VerifyOrExit((aPrf == OT_ROUTE_PREFERENCE_LOW) || (aPrf == OT_ROUTE_PREFERENCE_MED) || (aPrf == OT_ROUTE_PREFERENCE_HIGH), error = OT_ERROR_INVALID_ARGS); RemoveHasRoutePrefix(aPrefix, aPrefixLength); appendLength = sizeof(PrefixTlv) + prefixLengthBytes + sizeof(HasRouteTlv) + sizeof(HasRouteEntry); VerifyOrExit(mLength + appendLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS); prefixTlv = reinterpret_cast<PrefixTlv *>(mTlvs + mLength); Insert(reinterpret_cast<uint8_t *>(prefixTlv), appendLength); prefixTlv->Init(0, aPrefixLength, aPrefix); prefixTlv->SetSubTlvsLength(sizeof(HasRouteTlv) + sizeof(HasRouteEntry)); hasRouteTlv = static_cast<HasRouteTlv *>(prefixTlv->GetSubTlvs()); hasRouteTlv->Init(); hasRouteTlv->SetLength(hasRouteTlv->GetLength() + sizeof(HasRouteEntry)); hasRouteTlv->GetEntry(0)->Init(); hasRouteTlv->GetEntry(0)->SetPreference(aPrf); if (aStable) { prefixTlv->SetStable(); hasRouteTlv->SetStable(); } ClearResubmitDelayTimer(); otDumpDebgNetData("add route done", mTlvs, mLength); exit: return error; }
void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength) { NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(aData); NetworkDataTlv *end; PrefixTlv *prefix; uint8_t length; uint8_t *dst; uint8_t *src; while (1) { end = reinterpret_cast<NetworkDataTlv *>(aData + aDataLength); if (cur >= end) { break; } switch (cur->GetType()) { case NetworkDataTlv::kTypePrefix: { prefix = reinterpret_cast<PrefixTlv *>(cur); RemoveTemporaryData(aData, aDataLength, *prefix); if (prefix->GetSubTlvsLength() == 0) { length = sizeof(NetworkDataTlv) + cur->GetLength(); dst = reinterpret_cast<uint8_t *>(cur); src = reinterpret_cast<uint8_t *>(cur->GetNext()); memmove(dst, src, aDataLength - (src - aData)); aDataLength -= length; continue; } otDumpDebgNetData("remove prefix done", mTlvs, mLength); break; } default: { // remove temporary tlv if (!cur->IsStable()) { length = sizeof(NetworkDataTlv) + cur->GetLength(); dst = reinterpret_cast<uint8_t *>(cur); src = reinterpret_cast<uint8_t *>(cur->GetNext()); memmove(dst, src, aDataLength - (src - aData)); aDataLength -= length; continue; } break; } } cur = cur->GetNext(); } otDumpDebgNetData("remove done", aData, aDataLength); }