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 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 JoinerRouter::SendDelayedJoinerEntrust(void) { ThreadNetif & netif = GetNetif(); DelayedJoinEntHeader delayedJoinEnt; Coap::Message * message = static_cast<Coap::Message *>(mDelayedJoinEnts.GetHead()); uint32_t now = TimerMilli::GetNow(); Ip6::MessageInfo messageInfo; VerifyOrExit(message != NULL); VerifyOrExit(!mTimer.IsRunning()); delayedJoinEnt.ReadFrom(*message); // The message can be sent during CoAP transaction if KEK did not change (i.e. retransmission). VerifyOrExit(!mExpectJoinEntRsp || memcmp(netif.GetKeyManager().GetKek(), delayedJoinEnt.GetKek(), KeyManager::kMaxKeyLength) == 0); if (delayedJoinEnt.IsLater(now)) { mTimer.Start(delayedJoinEnt.GetSendTime() - now); } else { mDelayedJoinEnts.Dequeue(*message); // Remove the DelayedJoinEntHeader from the message. DelayedJoinEntHeader::RemoveFrom(*message); // Set KEK to one used for this message. netif.GetKeyManager().SetKek(delayedJoinEnt.GetKek()); // Send the message. memcpy(&messageInfo, delayedJoinEnt.GetMessageInfo(), sizeof(messageInfo)); if (SendJoinerEntrust(*message, messageInfo) != OT_ERROR_NONE) { message->Free(); mTimer.Start(0); } } exit: return; }
otError JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessageInfo, const JoinerRouterKekTlv &aKek) { ThreadNetif & netif = GetNetif(); otError error; Coap::Message * message = NULL; Ip6::MessageInfo messageInfo; Dataset dataset(MeshCoP::Tlv::kActiveTimestamp); NetworkMasterKeyTlv masterKey; MeshLocalPrefixTlv meshLocalPrefix; ExtendedPanIdTlv extendedPanId; NetworkNameTlv networkName; NetworkKeySequenceTlv networkKeySequence; const Tlv * tlv; DelayedJoinEntHeader delayedMessage; VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap())) != NULL, error = OT_ERROR_NO_BUFS); message->Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); message->AppendUriPathOptions(OT_URI_PATH_JOINER_ENTRUST); message->SetPayloadMarker(); message->SetSubType(Message::kSubTypeJoinerEntrust); masterKey.Init(); masterKey.SetNetworkMasterKey(netif.GetKeyManager().GetMasterKey()); SuccessOrExit(error = message->Append(&masterKey, sizeof(masterKey))); meshLocalPrefix.Init(); meshLocalPrefix.SetMeshLocalPrefix(netif.GetMle().GetMeshLocalPrefix()); SuccessOrExit(error = message->Append(&meshLocalPrefix, sizeof(meshLocalPrefix))); extendedPanId.Init(); extendedPanId.SetExtendedPanId(netif.GetMac().GetExtendedPanId()); SuccessOrExit(error = message->Append(&extendedPanId, sizeof(extendedPanId))); networkName.Init(); networkName.SetNetworkName(netif.GetMac().GetNetworkName()); SuccessOrExit(error = message->Append(&networkName, sizeof(Tlv) + networkName.GetLength())); netif.GetActiveDataset().Get(dataset); if ((tlv = dataset.Get(Tlv::kActiveTimestamp)) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } else { ActiveTimestampTlv activeTimestamp; activeTimestamp.Init(); SuccessOrExit(error = message->Append(&activeTimestamp, sizeof(activeTimestamp))); } if ((tlv = dataset.Get(Tlv::kChannelMask)) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } else { ChannelMaskBaseTlv channelMask; channelMask.Init(); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); } if ((tlv = dataset.Get(Tlv::kPSKc)) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } else { PSKcTlv pskc; pskc.Init(); SuccessOrExit(error = message->Append(&pskc, sizeof(pskc))); } if ((tlv = dataset.Get(Tlv::kSecurityPolicy)) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } else { SecurityPolicyTlv securityPolicy; securityPolicy.Init(); SuccessOrExit(error = message->Append(&securityPolicy, sizeof(securityPolicy))); } networkKeySequence.Init(); networkKeySequence.SetNetworkKeySequence(netif.GetKeyManager().GetCurrentKeySequence()); SuccessOrExit(error = message->Append(&networkKeySequence, networkKeySequence.GetSize())); messageInfo = aMessageInfo; messageInfo.SetPeerPort(kCoapUdpPort); delayedMessage = DelayedJoinEntHeader(TimerMilli::GetNow() + kDelayJoinEnt, messageInfo, aKek.GetKek()); SuccessOrExit(delayedMessage.AppendTo(*message)); mDelayedJoinEnts.Enqueue(*message); if (!mTimer.IsRunning()) { mTimer.Start(kDelayJoinEnt); } exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return 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; }