void PanIdQueryClient::HandleConflict(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif &netif = GetNetif(); MeshCoP::PanIdTlv panId; MeshCoP::ChannelMask0Tlv channelMask; Ip6::MessageInfo responseInfo(aMessageInfo); VerifyOrExit(aHeader.GetType() == OT_COAP_TYPE_CONFIRMABLE && aHeader.GetCode() == OT_COAP_CODE_POST); otLogInfoMeshCoP(GetInstance(), "received panid conflict"); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kPanId, sizeof(panId), panId)); VerifyOrExit(panId.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kChannelMask, sizeof(channelMask), channelMask)); VerifyOrExit(channelMask.IsValid()); if (mCallback != NULL) { mCallback(panId.GetPanId(), channelMask.GetMask(), mContext); } SuccessOrExit(netif.GetCoap().SendEmptyAck(aHeader, responseInfo)); otLogInfoMeshCoP(GetInstance(), "sent panid query conflict response"); exit: return; }
void EnergyScanClient::HandleReport(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { uint32_t mask; OT_TOOL_PACKED_BEGIN struct { MeshCoP::EnergyListTlv tlv; uint8_t list[OPENTHREAD_CONFIG_MAX_ENERGY_RESULTS]; } OT_TOOL_PACKED_END energyList; VerifyOrExit(aMessage.GetType() == OT_COAP_TYPE_CONFIRMABLE && aMessage.GetCode() == OT_COAP_CODE_POST); otLogInfoMeshCoP("received energy scan report"); VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kEnergyList, sizeof(energyList), energyList.tlv)); VerifyOrExit(energyList.tlv.IsValid()); if (mCallback != NULL) { mCallback(mask, energyList.list, energyList.tlv.GetLength(), mContext); } SuccessOrExit(Get<Coap::Coap>().SendEmptyAck(aMessage, aMessageInfo)); otLogInfoMeshCoP("sent energy scan report response"); exit: return; }
void EnergyScanClient::HandleReport(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif & netif = GetNetif(); MeshCoP::ChannelMaskTlv channelMask; Ip6::MessageInfo responseInfo(aMessageInfo); OT_TOOL_PACKED_BEGIN struct { MeshCoP::EnergyListTlv tlv; uint8_t list[OPENTHREAD_CONFIG_MAX_ENERGY_RESULTS]; } OT_TOOL_PACKED_END energyList; VerifyOrExit(aMessage.GetType() == OT_COAP_TYPE_CONFIRMABLE && aMessage.GetCode() == OT_COAP_CODE_POST); otLogInfoMeshCoP("received energy scan report"); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kChannelMask, sizeof(channelMask), channelMask)); VerifyOrExit(channelMask.IsValid() && channelMask.GetChannelPage() == OT_RADIO_CHANNEL_PAGE); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kEnergyList, sizeof(energyList), energyList.tlv)); VerifyOrExit(energyList.tlv.IsValid()); if (mCallback != NULL) { mCallback(channelMask.GetMask(), energyList.list, energyList.tlv.GetLength(), mContext); } SuccessOrExit(netif.GetCoap().SendEmptyAck(aMessage, responseInfo)); otLogInfoMeshCoP("sent energy scan report response"); exit: return; }
void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif & netif = GetNetif(); otError error; Coap::Message * message = NULL; Ip6::MessageInfo messageInfo; JoinerUdpPortTlv udpPort; JoinerIidTlv iid; JoinerRouterLocatorTlv rloc; ExtendedTlv tlv; uint16_t borderAgentRloc; uint16_t offset; otLogInfoMeshCoP("JoinerRouter::HandleUdpReceive"); SuccessOrExit(error = GetBorderAgentRloc(GetNetif(), borderAgentRloc)); VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap())) != NULL, error = OT_ERROR_NO_BUFS); message->Init(OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_POST); message->SetToken(Coap::Message::kDefaultTokenLength); message->AppendUriPathOptions(OT_URI_PATH_RELAY_RX); message->SetPayloadMarker(); udpPort.Init(); udpPort.SetUdpPort(aMessageInfo.GetPeerPort()); SuccessOrExit(error = message->Append(&udpPort, sizeof(udpPort))); iid.Init(); iid.SetIid(aMessageInfo.GetPeerAddr().mFields.m8 + 8); SuccessOrExit(error = message->Append(&iid, sizeof(iid))); rloc.Init(); rloc.SetJoinerRouterLocator(netif.GetMle().GetRloc16()); SuccessOrExit(error = message->Append(&rloc, sizeof(rloc))); tlv.SetType(Tlv::kJoinerDtlsEncapsulation); tlv.SetLength(aMessage.GetLength() - aMessage.GetOffset()); SuccessOrExit(error = message->Append(&tlv, sizeof(tlv))); offset = message->GetLength(); SuccessOrExit(error = message->SetLength(offset + tlv.GetLength())); aMessage.CopyTo(aMessage.GetOffset(), offset, tlv.GetLength(), *message); messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(netif.GetMle().GetMeshLocal16()); messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(borderAgentRloc); messageInfo.SetPeerPort(kCoapUdpPort); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP("Sent relay rx"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } }
void Leader::ResignCommissioner(void) { mTimer.Stop(); SetEmptyCommissionerData(); otLogInfoMeshCoP(GetInstance(), "commissioner inactive"); }
otError Leader::SendDatasetChanged(const Ip6::Address &aAddress) { ThreadNetif &netif = GetNetif(); otError error = OT_ERROR_NONE; Coap::Header header; Ip6::MessageInfo messageInfo; Message *message; header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OT_URI_PATH_DATASET_CHANGED); VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS); messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(aAddress); messageInfo.SetPeerPort(kCoapUdpPort); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP(GetInstance(), "sent dataset changed"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
otError Leader::SendKeepAliveResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo, StateTlv::State aState) { ThreadNetif &netif = GetNetif(); otError error = OT_ERROR_NONE; Coap::Header responseHeader; StateTlv state; Message *message; responseHeader.SetDefaultResponseHeader(aRequestHeader); responseHeader.SetPayloadMarker(); VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), responseHeader)) != NULL, error = OT_ERROR_NO_BUFS); state.Init(); state.SetState(aState); SuccessOrExit(error = message->Append(&state, sizeof(state))); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, aMessageInfo)); otLogInfoMeshCoP(GetInstance(), "sent keep alive response"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
void Leader::HandleKeepAlive(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { StateTlv state; CommissionerSessionIdTlv sessionId; StateTlv::State responseState; otLogInfoMeshCoP(GetInstance(), "received keep alive"); SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kState, sizeof(state), state)); VerifyOrExit(state.IsValid()); SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerSessionId, sizeof(sessionId), sessionId)); VerifyOrExit(sessionId.IsValid()); if (sessionId.GetCommissionerSessionId() != mSessionId) { responseState = StateTlv::kReject; } else if (state.GetState() != StateTlv::kAccept) { responseState = StateTlv::kReject; ResignCommissioner(); } else { responseState = StateTlv::kAccept; mTimer.Start(TimerMilli::SecToMsec(kTimeoutLeaderPetition)); } SendKeepAliveResponse(aHeader, aMessageInfo, responseState); exit: return; }
void Joiner::SendJoinerEntrustResponse(const Coap::Message &aRequest, const Ip6::MessageInfo &aRequestInfo) { ThreadNetif & netif = GetNetif(); otError error = OT_ERROR_NONE; Coap::Message * message; Ip6::MessageInfo responseInfo(aRequestInfo); VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap())) != NULL, error = OT_ERROR_NO_BUFS); message->SetDefaultResponseHeader(aRequest); message->SetSubType(Message::kSubTypeJoinerEntrust); memset(&responseInfo.mSockAddr, 0, sizeof(responseInfo.mSockAddr)); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, responseInfo)); mState = OT_JOINER_STATE_JOINED; otLogInfoArp("Sent Joiner Entrust response"); otLogInfoMeshCoP("Sent joiner entrust response length = %d", message->GetLength()); otLogCertMeshCoP("[THCI] direction=send | type=JOIN_ENT.rsp"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } }
void AnnounceBeginServer::HandleRequest(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { MeshCoP::ChannelMask0Tlv channelMask; MeshCoP::CountTlv count; MeshCoP::PeriodTlv period; Ip6::MessageInfo responseInfo(aMessageInfo); VerifyOrExit(aHeader.GetCode() == OT_COAP_CODE_POST); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kChannelMask, sizeof(channelMask), channelMask)); VerifyOrExit(channelMask.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kCount, sizeof(count), count)); VerifyOrExit(count.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kPeriod, sizeof(period), period)); VerifyOrExit(period.IsValid()); SendAnnounce(channelMask.GetMask(), count.GetCount(), period.GetPeriod()); if (aHeader.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast()) { SuccessOrExit(GetNetif().GetCoap().SendEmptyAck(aHeader, responseInfo)); otLogInfoMeshCoP(GetInstance(), "sent announce begin response"); } exit: return; }
void JoinerRouter::HandleStateChanged(otChangedFlags aFlags) { ThreadNetif &netif = GetNetif(); VerifyOrExit(netif.GetMle().IsFullThreadDevice()); VerifyOrExit(aFlags & OT_CHANGED_THREAD_NETDATA); netif.GetIp6Filter().RemoveUnsecurePort(mSocket.GetSockName().mPort); if (netif.GetNetworkDataLeader().IsJoiningEnabled()) { Ip6::SockAddr sockaddr; sockaddr.mPort = GetJoinerUdpPort(); mSocket.Open(&JoinerRouter::HandleUdpReceive, this); mSocket.Bind(sockaddr); netif.GetIp6Filter().AddUnsecurePort(sockaddr.mPort); otLogInfoMeshCoP("Joiner Router: start"); } else { mSocket.Close(); } exit: return; }
void Joiner::HandleJoinerFinalizeResponse(Coap::Message & aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult) { OT_UNUSED_VARIABLE(aMessageInfo); StateTlv state; VerifyOrExit(mState == OT_JOINER_STATE_CONNECTED && aResult == OT_ERROR_NONE && aMessage.GetType() == OT_COAP_TYPE_ACKNOWLEDGMENT && aMessage.GetCode() == OT_COAP_CODE_CHANGED); SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kState, sizeof(state), state)); VerifyOrExit(state.IsValid()); mState = OT_JOINER_STATE_ENTRUST; mTimer.Start(kTimeout); otLogInfoMeshCoP("received joiner finalize response %d", static_cast<uint8_t>(state.GetState())); #if OPENTHREAD_ENABLE_CERT_LOG uint8_t buf[OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE]; VerifyOrExit(aMessage.GetLength() <= sizeof(buf)); aMessage.Read(aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset(), buf); otDumpCertMeshCoP("[THCI] direction=recv | type=JOIN_FIN.rsp |", buf, aMessage.GetLength() - aMessage.GetOffset()); #endif exit: Close(); }
otError AnnounceBeginClient::SendRequest(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod, const Ip6::Address &aAddress) { otError error = OT_ERROR_NONE; Coap::Header header; MeshCoP::CommissionerSessionIdTlv sessionId; MeshCoP::ChannelMask0Tlv channelMask; MeshCoP::CountTlv count; MeshCoP::PeriodTlv period; Ip6::MessageInfo messageInfo; Message *message = NULL; VerifyOrExit(GetNetif().GetCommissioner().IsActive(), error = OT_ERROR_INVALID_STATE); header.Init(aAddress.IsMulticast() ? OT_COAP_TYPE_NON_CONFIRMABLE : OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OT_URI_PATH_ANNOUNCE_BEGIN); header.SetPayloadMarker(); VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(GetNetif().GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS); sessionId.Init(); sessionId.SetCommissionerSessionId(GetNetif().GetCommissioner().GetSessionId()); SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId))); channelMask.Init(); channelMask.SetMask(aChannelMask); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); count.Init(); count.SetCount(aCount); SuccessOrExit(error = message->Append(&count, sizeof(count))); period.Init(); period.SetPeriod(aPeriod); SuccessOrExit(error = message->Append(&period, sizeof(period))); messageInfo.SetSockAddr(GetNetif().GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(aAddress); messageInfo.SetPeerPort(kCoapUdpPort); messageInfo.SetInterfaceId(GetNetif().GetInterfaceId()); SuccessOrExit(error = GetNetif().GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP(GetInstance(), "sent announce begin query"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
otError JoinerRouter::SendJoinerEntrust(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif &netif = GetNetif(); otError error; netif.GetCoap().AbortTransaction(&JoinerRouter::HandleJoinerEntrustResponse, this); otLogInfoMeshCoP("Sending JOIN_ENT.ntf"); SuccessOrExit( error = netif.GetCoap().SendMessage(aMessage, aMessageInfo, &JoinerRouter::HandleJoinerEntrustResponse, this)); otLogInfoMeshCoP("Sent joiner entrust length = %d", aMessage.GetLength()); otLogCertMeshCoP("[THCI] direction=send | type=JOIN_ENT.ntf"); mExpectJoinEntRsp = true; exit: return error; }
otError PanIdQueryClient::SendQuery(uint16_t aPanId, uint32_t aChannelMask, const Ip6::Address &aAddress, otCommissionerPanIdConflictCallback aCallback, void *aContext) { ThreadNetif &netif = GetNetif(); otError error = OT_ERROR_NONE; Coap::Header header; MeshCoP::CommissionerSessionIdTlv sessionId; MeshCoP::ChannelMask0Tlv channelMask; MeshCoP::PanIdTlv panId; Ip6::MessageInfo messageInfo; Message *message = NULL; VerifyOrExit(netif.GetCommissioner().IsActive(), error = OT_ERROR_INVALID_STATE); header.Init(aAddress.IsMulticast() ? OT_COAP_TYPE_NON_CONFIRMABLE : OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OT_URI_PATH_PANID_QUERY); header.SetPayloadMarker(); VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS); sessionId.Init(); sessionId.SetCommissionerSessionId(netif.GetCommissioner().GetSessionId()); SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId))); channelMask.Init(); channelMask.SetMask(aChannelMask); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); panId.Init(); panId.SetPanId(aPanId); SuccessOrExit(error = message->Append(&panId, sizeof(panId))); messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(aAddress); messageInfo.SetPeerPort(kCoapUdpPort); messageInfo.SetInterfaceId(netif.GetInterfaceId()); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP(GetInstance(), "sent panid query"); mCallback = aCallback; mContext = aContext; exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
otError Leader::SendPetitionResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo, StateTlv::State aState) { ThreadNetif &netif = GetNetif(); otError error = OT_ERROR_NONE; Coap::Header responseHeader; StateTlv state; CommissionerSessionIdTlv sessionId; Message *message; responseHeader.SetDefaultResponseHeader(aRequestHeader); responseHeader.SetPayloadMarker(); VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), responseHeader)) != NULL, error = OT_ERROR_NO_BUFS); state.Init(); state.SetState(aState); SuccessOrExit(error = message->Append(&state, sizeof(state))); if (mTimer.IsRunning()) { uint16_t len = sizeof(Tlv) + mCommissionerId.GetLength(); SuccessOrExit(error = message->Append(&mCommissionerId, len)); } if (aState == StateTlv::kAccept) { sessionId.Init(); sessionId.SetCommissionerSessionId(mSessionId); SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId))); } SuccessOrExit(error = netif.GetCoap().SendMessage(*message, aMessageInfo)); otLogInfoMeshCoP(GetInstance(), "sent petition response"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
otError EnergyScanServer::SendReport(void) { otError error = OT_ERROR_NONE; Coap::Header header; MeshCoP::ChannelMask0Tlv channelMask; MeshCoP::EnergyListTlv energyList; Ip6::MessageInfo messageInfo; Message * message; header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OT_URI_PATH_ENERGY_REPORT); header.SetPayloadMarker(); VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(GetNetif().GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS); channelMask.Init(); channelMask.SetMask(mChannelMask); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); energyList.Init(); energyList.SetLength(mScanResultsLength); SuccessOrExit(error = message->Append(&energyList, sizeof(energyList))); SuccessOrExit(error = message->Append(mScanResults, mScanResultsLength)); messageInfo.SetSockAddr(GetNetif().GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(mCommissioner); messageInfo.SetPeerPort(kCoapUdpPort); SuccessOrExit(error = GetNetif().GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP(GetInstance(), "sent scan results"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } mActive = false; return error; }
void JoinerRouter::HandleJoinerEntrustResponse(Coap::Message * aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult) { OT_UNUSED_VARIABLE(aMessageInfo); mExpectJoinEntRsp = false; SendDelayedJoinerEntrust(); VerifyOrExit(aResult == OT_ERROR_NONE && aMessage != NULL); VerifyOrExit(aMessage->GetCode() == OT_COAP_CODE_CHANGED); otLogInfoMeshCoP("Receive joiner entrust response"); otLogCertMeshCoP("[THCI] direction=recv | type=JOIN_ENT.rsp"); exit: return; }
void EnergyScanServer::HandleRequest(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { MeshCoP::CountTlv count; MeshCoP::PeriodTlv period; MeshCoP::ScanDurationTlv scanDuration; MeshCoP::ChannelMask0Tlv channelMask; Ip6::MessageInfo responseInfo(aMessageInfo); VerifyOrExit(aHeader.GetCode() == OT_COAP_CODE_POST); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kCount, sizeof(count), count)); VerifyOrExit(count.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kPeriod, sizeof(period), period)); VerifyOrExit(period.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kScanDuration, sizeof(scanDuration), scanDuration)); VerifyOrExit(scanDuration.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kChannelMask, sizeof(channelMask), channelMask)); VerifyOrExit(channelMask.IsValid()); mChannelMask = channelMask.GetMask(); mChannelMaskCurrent = mChannelMask; mCount = count.GetCount(); mPeriod = period.GetPeriod(); mScanDuration = scanDuration.GetScanDuration(); mScanResultsLength = 0; mActive = true; mTimer.Start(kScanDelay); mCommissioner = aMessageInfo.GetPeerAddr(); if (aHeader.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast()) { SuccessOrExit(GetNetif().GetCoap().SendEmptyAck(aHeader, responseInfo)); otLogInfoMeshCoP(GetInstance(), "sent energy scan query response"); } exit: return; }
void Leader::HandlePetition(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { CommissioningData data; CommissionerIdTlv commissionerId; StateTlv::State state = StateTlv::kReject; otLogInfoMeshCoP(GetInstance(), "received petition"); SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerId, sizeof(commissionerId), commissionerId)); VerifyOrExit(commissionerId.IsValid()); if (mTimer.IsRunning()) { VerifyOrExit(!strncmp(commissionerId.GetCommissionerId(), mCommissionerId.GetCommissionerId(), sizeof(mCommissionerId))); ResignCommissioner(); } data.mBorderAgentLocator.Init(); data.mBorderAgentLocator.SetBorderAgentLocator(HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7])); data.mCommissionerSessionId.Init(); data.mCommissionerSessionId.SetCommissionerSessionId(++mSessionId); data.mSteeringData.Init(); data.mSteeringData.SetLength(1); data.mSteeringData.Clear(); SuccessOrExit(GetNetif().GetNetworkDataLeader().SetCommissioningData(reinterpret_cast<uint8_t *>(&data), data.GetLength())); mCommissionerId = commissionerId; state = StateTlv::kAccept; mTimer.Start(TimerMilli::SecToMsec(kTimeoutLeaderPetition)); exit: OT_UNUSED_VARIABLE(aMessageInfo); SendPetitionResponse(aHeader, aMessageInfo, state); }
ThreadError DatasetManager::Register(void) { ThreadError error = kThreadError_None; Coap::Header header; Message *message; Ip6::Address leader; Ip6::MessageInfo messageInfo; header.Init(kCoapTypeConfirmable, kCoapRequestPost); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(mUriSet); header.SetPayloadMarker(); if (strcmp(mUriSet, OPENTHREAD_URI_PENDING_SET) == 0) { PendingDatasetBase *pending = static_cast<PendingDatasetBase *>(this); pending->UpdateDelayTimer(); } VerifyOrExit((message = mNetif.GetCoapClient().NewMeshCoPMessage(header)) != NULL, error = kThreadError_NoBufs); SuccessOrExit(error = message->Append(mLocal.GetBytes(), mLocal.GetSize())); mNetif.GetMle().GetLeaderAloc(leader); messageInfo.SetPeerAddr(leader); messageInfo.SetPeerPort(kCoapUdpPort); SuccessOrExit(error = mNetif.GetCoapClient().SendMessage(*message, messageInfo)); otLogInfoMeshCoP("sent dataset to leader"); exit: if (error != kThreadError_None && message != NULL) { message->Free(); } return error; }
void JoinerRouter::HandleRelayTransmit(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { OT_UNUSED_VARIABLE(aMessageInfo); otError error; JoinerUdpPortTlv joinerPort; JoinerIidTlv joinerIid; JoinerRouterKekTlv kek; uint16_t offset; uint16_t length; Message * message = NULL; otMessageSettings settings = {false, static_cast<otMessagePriority>(kMeshCoPMessagePriority)}; Ip6::MessageInfo messageInfo; VerifyOrExit(aMessage.GetType() == OT_COAP_TYPE_NON_CONFIRMABLE && aMessage.GetCode() == OT_COAP_CODE_POST, error = OT_ERROR_DROP); otLogInfoMeshCoP("Received relay transmit"); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kJoinerUdpPort, sizeof(joinerPort), joinerPort)); VerifyOrExit(joinerPort.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kJoinerIid, sizeof(joinerIid), joinerIid)); VerifyOrExit(joinerIid.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetValueOffset(aMessage, Tlv::kJoinerDtlsEncapsulation, offset, length)); VerifyOrExit((message = mSocket.NewMessage(0, &settings)) != NULL, error = OT_ERROR_NO_BUFS); while (length) { uint16_t copyLength = length; uint8_t tmp[16]; if (copyLength >= sizeof(tmp)) { copyLength = sizeof(tmp); } aMessage.Read(offset, copyLength, tmp); SuccessOrExit(error = message->Append(tmp, copyLength)); offset += copyLength; length -= copyLength; } aMessage.CopyTo(offset, 0, length, *message); messageInfo.mPeerAddr.mFields.m16[0] = HostSwap16(0xfe80); memcpy(messageInfo.mPeerAddr.mFields.m8 + 8, joinerIid.GetIid(), 8); messageInfo.SetPeerPort(joinerPort.GetUdpPort()); messageInfo.SetInterfaceId(GetNetif().GetInterfaceId()); SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); if (Tlv::GetTlv(aMessage, Tlv::kJoinerRouterKek, sizeof(kek), kek) == OT_ERROR_NONE) { otLogInfoMeshCoP("Received kek"); DelaySendingJoinerEntrust(messageInfo, kek); } exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } }
otError Dtls::Setup(bool aClient) { int rval; // do not handle new connection before guard time expired VerifyOrExit(mState == kStateOpen, rval = MBEDTLS_ERR_SSL_TIMEOUT); mState = kStateInitializing; mbedtls_ssl_init(&mSsl); mbedtls_ssl_config_init(&mConf); mbedtls_ctr_drbg_init(&mCtrDrbg); mbedtls_entropy_init(&mEntropy); #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED mbedtls_x509_crt_init(&mCaChain); mbedtls_x509_crt_init(&mOwnCert); mbedtls_pk_init(&mPrivateKey); #endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE rval = mbedtls_entropy_add_source(&mEntropy, &Dtls::HandleMbedtlsEntropyPoll, NULL, MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_SOURCE_STRONG); VerifyOrExit(rval == 0); { otExtAddress eui64; otPlatRadioGetIeeeEui64(&GetInstance(), eui64.m8); rval = mbedtls_ctr_drbg_seed(&mCtrDrbg, mbedtls_entropy_func, &mEntropy, eui64.m8, sizeof(eui64)); VerifyOrExit(rval == 0); } rval = mbedtls_ssl_config_defaults(&mConf, aClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT); VerifyOrExit(rval == 0); #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE if (mVerifyPeerCertificate && mCipherSuites[0] == MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8) { mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_REQUIRED); } else { mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_NONE); } #else OT_UNUSED_VARIABLE(mVerifyPeerCertificate); #endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE mbedtls_ssl_conf_rng(&mConf, mbedtls_ctr_drbg_random, &mCtrDrbg); mbedtls_ssl_conf_min_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); mbedtls_ssl_conf_max_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); mbedtls_ssl_conf_ciphersuites(&mConf, mCipherSuites); mbedtls_ssl_conf_export_keys_cb(&mConf, HandleMbedtlsExportKeys, this); mbedtls_ssl_conf_handshake_timeout(&mConf, 8000, 60000); mbedtls_ssl_conf_dbg(&mConf, HandleMbedtlsDebug, this); #if OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER || OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE if (!aClient) { mbedtls_ssl_cookie_init(&mCookieCtx); rval = mbedtls_ssl_cookie_setup(&mCookieCtx, mbedtls_ctr_drbg_random, &mCtrDrbg); VerifyOrExit(rval == 0); mbedtls_ssl_conf_dtls_cookies(&mConf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &mCookieCtx); } #endif // OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER || OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE rval = mbedtls_ssl_setup(&mSsl, &mConf); VerifyOrExit(rval == 0); mbedtls_ssl_set_bio(&mSsl, this, &Dtls::HandleMbedtlsTransmit, HandleMbedtlsReceive, NULL); mbedtls_ssl_set_timer_cb(&mSsl, this, &Dtls::HandleMbedtlsSetTimer, HandleMbedtlsGetTimer); if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8) { rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength); } #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE else { rval = SetApplicationCoapSecureKeys(); } #endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE VerifyOrExit(rval == 0); mReceiveMessage = NULL; mMessageSubType = Message::kSubTypeNone; mState = kStateConnecting; if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8) { otLogInfoMeshCoP("DTLS started"); } #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE else { otLogInfoCoap("Application Coap Secure DTLS started"); } #endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE mState = kStateConnecting; Process(); exit: if ((mState == kStateInitializing) && (rval != 0)) { mState = kStateOpen; FreeMbedtls(); } return MapError(rval); }
void Joiner::HandleJoinerEntrust(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif & netif = GetNetif(); otError error; NetworkMasterKeyTlv masterKey; MeshLocalPrefixTlv meshLocalPrefix; ExtendedPanIdTlv extendedPanId; NetworkNameTlv networkName; ActiveTimestampTlv activeTimestamp; NetworkKeySequenceTlv networkKeySeq; VerifyOrExit(mState == OT_JOINER_STATE_ENTRUST && aMessage.GetType() == OT_COAP_TYPE_CONFIRMABLE && aMessage.GetCode() == OT_COAP_CODE_POST, error = OT_ERROR_DROP); otLogInfoMeshCoP("Received joiner entrust"); otLogCertMeshCoP("[THCI] direction=recv | type=JOIN_ENT.ntf"); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kNetworkMasterKey, sizeof(masterKey), masterKey)); VerifyOrExit(masterKey.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kMeshLocalPrefix, sizeof(meshLocalPrefix), meshLocalPrefix)); VerifyOrExit(meshLocalPrefix.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kExtendedPanId, sizeof(extendedPanId), extendedPanId)); VerifyOrExit(extendedPanId.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kNetworkName, sizeof(networkName), networkName)); VerifyOrExit(networkName.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kActiveTimestamp, sizeof(activeTimestamp), activeTimestamp)); VerifyOrExit(activeTimestamp.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kNetworkKeySequence, sizeof(networkKeySeq), networkKeySeq)); VerifyOrExit(networkKeySeq.IsValid(), error = OT_ERROR_PARSE); netif.GetKeyManager().SetMasterKey(masterKey.GetNetworkMasterKey()); netif.GetKeyManager().SetCurrentKeySequence(networkKeySeq.GetNetworkKeySequence()); netif.GetMle().SetMeshLocalPrefix(meshLocalPrefix.GetMeshLocalPrefix()); netif.GetMac().SetExtendedPanId(extendedPanId.GetExtendedPanId()); { otNetworkName name; memcpy(name.m8, networkName.GetNetworkName(), networkName.GetLength()); name.m8[networkName.GetLength()] = '\0'; netif.GetMac().SetNetworkName(name.m8); } otLogInfoMeshCoP("join success!"); // Send dummy response. SendJoinerEntrustResponse(aMessage, aMessageInfo); // Delay extended address configuration to allow DTLS wrap up. mTimer.Start(kConfigExtAddressDelay); exit: if (error != OT_ERROR_NONE) { otLogWarnMeshCoP("Error while processing joiner entrust: %s", otThreadErrorToString(error)); } }
void Joiner::SendJoinerFinalize(void) { ThreadNetif & netif = GetNetif(); otError error = OT_ERROR_NONE; Coap::Message * message = NULL; StateTlv stateTlv; VendorNameTlv vendorNameTlv; VendorModelTlv vendorModelTlv; VendorSwVersionTlv vendorSwVersionTlv; VendorStackVersionTlv vendorStackVersionTlv; VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoapSecure())) != NULL, error = OT_ERROR_NO_BUFS); message->Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); message->AppendUriPathOptions(OT_URI_PATH_JOINER_FINALIZE); message->SetPayloadMarker(); message->SetOffset(message->GetLength()); stateTlv.Init(); stateTlv.SetState(MeshCoP::StateTlv::kAccept); SuccessOrExit(error = message->Append(&stateTlv, sizeof(stateTlv))); vendorNameTlv.Init(); vendorNameTlv.SetVendorName(mVendorName); SuccessOrExit(error = message->Append(&vendorNameTlv, vendorNameTlv.GetSize())); vendorModelTlv.Init(); vendorModelTlv.SetVendorModel(mVendorModel); SuccessOrExit(error = message->Append(&vendorModelTlv, vendorModelTlv.GetSize())); vendorSwVersionTlv.Init(); vendorSwVersionTlv.SetVendorSwVersion(mVendorSwVersion); SuccessOrExit(error = message->Append(&vendorSwVersionTlv, vendorSwVersionTlv.GetSize())); vendorStackVersionTlv.Init(); vendorStackVersionTlv.SetOui(OPENTHREAD_CONFIG_STACK_VENDOR_OUI); vendorStackVersionTlv.SetMajor(OPENTHREAD_CONFIG_STACK_VERSION_MAJOR); vendorStackVersionTlv.SetMinor(OPENTHREAD_CONFIG_STACK_VERSION_MINOR); vendorStackVersionTlv.SetRevision(OPENTHREAD_CONFIG_STACK_VERSION_REV); SuccessOrExit(error = message->Append(&vendorStackVersionTlv, vendorStackVersionTlv.GetSize())); if (mVendorData != NULL) { VendorDataTlv vendorDataTlv; vendorDataTlv.Init(); vendorDataTlv.SetVendorData(mVendorData); SuccessOrExit(error = message->Append(&vendorDataTlv, vendorDataTlv.GetSize())); } if (netif.GetCoapSecure().GetDtls().mProvisioningUrl.GetLength() > 0) { SuccessOrExit(error = message->Append(&netif.GetCoapSecure().GetDtls().mProvisioningUrl, netif.GetCoapSecure().GetDtls().mProvisioningUrl.GetSize())); } #if OPENTHREAD_ENABLE_CERT_LOG uint8_t buf[OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE]; VerifyOrExit(message->GetLength() <= sizeof(buf)); message->Read(message->GetOffset(), message->GetLength() - message->GetOffset(), buf); otDumpCertMeshCoP("[THCI] direction=send | type=JOIN_FIN.req |", buf, message->GetLength() - message->GetOffset()); #endif SuccessOrExit(error = netif.GetCoapSecure().SendMessage(*message, Joiner::HandleJoinerFinalizeResponse, this)); otLogInfoMeshCoP("Sent joiner finalize"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } }
otError EnergyScanClient::SendQuery(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod, uint16_t aScanDuration, const Ip6::Address & aAddress, otCommissionerEnergyReportCallback aCallback, void * aContext) { ThreadNetif & netif = GetNetif(); otError error = OT_ERROR_NONE; MeshCoP::CommissionerSessionIdTlv sessionId; MeshCoP::ChannelMaskTlv channelMask; MeshCoP::CountTlv count; MeshCoP::PeriodTlv period; MeshCoP::ScanDurationTlv scanDuration; Ip6::MessageInfo messageInfo; Coap::Message * message = NULL; VerifyOrExit(netif.GetCommissioner().IsActive(), error = OT_ERROR_INVALID_STATE); VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(netif.GetCoap())) != NULL, error = OT_ERROR_NO_BUFS); message->Init(aAddress.IsMulticast() ? OT_COAP_TYPE_NON_CONFIRMABLE : OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); message->SetToken(Coap::Message::kDefaultTokenLength); message->AppendUriPathOptions(OT_URI_PATH_ENERGY_SCAN); message->SetPayloadMarker(); sessionId.Init(); sessionId.SetCommissionerSessionId(netif.GetCommissioner().GetSessionId()); SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId))); channelMask.Init(); channelMask.SetChannelPage(OT_RADIO_CHANNEL_PAGE); channelMask.SetMask(aChannelMask); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); count.Init(); count.SetCount(aCount); SuccessOrExit(error = message->Append(&count, sizeof(count))); period.Init(); period.SetPeriod(aPeriod); SuccessOrExit(error = message->Append(&period, sizeof(period))); scanDuration.Init(); scanDuration.SetScanDuration(aScanDuration); SuccessOrExit(error = message->Append(&scanDuration, sizeof(scanDuration))); messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(aAddress); messageInfo.SetPeerPort(kCoapUdpPort); messageInfo.SetInterfaceId(netif.GetInterfaceId()); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP("sent energy scan query"); mCallback = aCallback; mContext = aContext; exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }