mirror of
https://github.com/espressif/openthread.git
synced 2026-07-28 06:37:46 +00:00
[srp-server] adding MessageMetadata (#7144)
This commit updates `Srp::Server` adding a new type `MessageMetadata`
which is used during processing of a received SRP Update message.
This class serves two purposes: (1) It helps simplify the code by
combining all related parameters (current offset in the message, DNS
`Header` and `Zone`, and `Ip6::MessageInfo`) into a single `struct`
which is then passed to different `Process{}()` methods. (2) It
defines new fields to represent the time when the message was
received (allowing us to process the message as if it was received
earlier than the current time) and the lease interval values to be
granted during processing of the message. These are added in
preparation for enabling SRP Replication (SRPL). With SRPL we can
receive an SRP Update message from an SRPL partner (i.e., another SRP
server) and then need to process it as if we received it on this
device at the same time as the original SRPL partner processed it and
with the same lease config values.
This commit is contained in:
+216
-202
@@ -352,7 +352,7 @@ void Server::HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError)
|
||||
otThreadErrorToString(aError));
|
||||
|
||||
IgnoreError(mOutstandingUpdates.Remove(*aUpdate));
|
||||
CommitSrpUpdate(aError, aUpdate->GetDnsHeader(), aUpdate->GetHost(), aUpdate->GetMessageInfo());
|
||||
CommitSrpUpdate(aError, *aUpdate);
|
||||
aUpdate->Free();
|
||||
|
||||
if (mOutstandingUpdates.IsEmpty())
|
||||
@@ -361,14 +361,28 @@ void Server::HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError)
|
||||
}
|
||||
else
|
||||
{
|
||||
mOutstandingUpdatesTimer.StartAt(mOutstandingUpdates.GetTail()->GetExpireTime(), 0);
|
||||
mOutstandingUpdatesTimer.FireAt(mOutstandingUpdates.GetTail()->GetExpireTime());
|
||||
}
|
||||
}
|
||||
|
||||
void Server::CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata)
|
||||
{
|
||||
CommitSrpUpdate(aError, aHost, aMessageMetadata.mDnsHeader, aMessageMetadata.mMessageInfo,
|
||||
aMessageMetadata.mLeaseConfig);
|
||||
}
|
||||
|
||||
void Server::CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata)
|
||||
{
|
||||
CommitSrpUpdate(aError, aUpdateMetadata.GetHost(), aUpdateMetadata.GetDnsHeader(),
|
||||
aUpdateMetadata.IsDirectRxFromClient() ? &aUpdateMetadata.GetMessageInfo() : nullptr,
|
||||
aUpdateMetadata.GetLeaseConfig());
|
||||
}
|
||||
|
||||
void Server::CommitSrpUpdate(Error aError,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
Host & aHost,
|
||||
const Ip6::MessageInfo & aMessageInfo)
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Ip6::MessageInfo * aMessageInfo,
|
||||
const LeaseConfig & aLeaseConfig)
|
||||
{
|
||||
Host * existingHost;
|
||||
uint32_t hostLease;
|
||||
@@ -381,8 +395,8 @@ void Server::CommitSrpUpdate(Error aError,
|
||||
|
||||
hostLease = aHost.GetLease();
|
||||
hostKeyLease = aHost.GetKeyLease();
|
||||
grantedLease = mLeaseConfig.GrantLease(hostLease);
|
||||
grantedKeyLease = mLeaseConfig.GrantKeyLease(hostKeyLease);
|
||||
grantedLease = aLeaseConfig.GrantLease(hostLease);
|
||||
grantedKeyLease = aLeaseConfig.GrantKeyLease(hostKeyLease);
|
||||
|
||||
aHost.SetLease(grantedLease);
|
||||
aHost.SetKeyLease(grantedKeyLease);
|
||||
@@ -446,13 +460,16 @@ void Server::CommitSrpUpdate(Error aError,
|
||||
HandleLeaseTimer();
|
||||
|
||||
exit:
|
||||
if (aError == kErrorNone && !(grantedLease == hostLease && grantedKeyLease == hostKeyLease))
|
||||
if (aMessageInfo != nullptr)
|
||||
{
|
||||
SendResponse(aDnsHeader, grantedLease, grantedKeyLease, aMessageInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendResponse(aDnsHeader, ErrorToDnsResponseCode(aError), aMessageInfo);
|
||||
if (aError == kErrorNone && !(grantedLease == hostLease && grantedKeyLease == hostKeyLease))
|
||||
{
|
||||
SendResponse(aDnsHeader, grantedLease, grantedKeyLease, *aMessageInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendResponse(aDnsHeader, ErrorToDnsResponseCode(aError), *aMessageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldFreeHost)
|
||||
@@ -618,16 +635,17 @@ void Server::HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent)
|
||||
}
|
||||
}
|
||||
|
||||
const Server::UpdateMetadata *Server::FindOutstandingUpdate(const Ip6::MessageInfo &aMessageInfo,
|
||||
uint16_t aDnsMessageId)
|
||||
const Server::UpdateMetadata *Server::FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const
|
||||
{
|
||||
const UpdateMetadata *ret = nullptr;
|
||||
|
||||
VerifyOrExit(aMessageMetadata.IsDirectRxFromClient());
|
||||
|
||||
for (const UpdateMetadata &update : mOutstandingUpdates)
|
||||
{
|
||||
if (aDnsMessageId == update.GetDnsHeader().GetMessageId() &&
|
||||
aMessageInfo.GetPeerAddr() == update.GetMessageInfo().GetPeerAddr() &&
|
||||
aMessageInfo.GetPeerPort() == update.GetMessageInfo().GetPeerPort())
|
||||
if (aMessageMetadata.mDnsHeader.GetMessageId() == update.GetDnsHeader().GetMessageId() &&
|
||||
aMessageMetadata.mMessageInfo->GetPeerAddr() == update.GetMessageInfo().GetPeerAddr() &&
|
||||
aMessageMetadata.mMessageInfo->GetPeerPort() == update.GetMessageInfo().GetPeerPort())
|
||||
{
|
||||
ExitNow(ret = &update);
|
||||
}
|
||||
@@ -637,22 +655,20 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Server::ProcessDnsUpdate(Message & aMessage,
|
||||
const Ip6::MessageInfo & aMessageInfo,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t aOffset)
|
||||
void Server::ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Dns::Zone zone;
|
||||
Host * host = nullptr;
|
||||
Error error = kErrorNone;
|
||||
Host *host = nullptr;
|
||||
|
||||
otLogInfoSrp("[server] receive DNS update from %s", aMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
otLogInfoSrp("[server] Received DNS update from %s",
|
||||
aMetadata.IsDirectRxFromClient() ? aMetadata.mMessageInfo->GetPeerAddr().ToString().AsCString()
|
||||
: "an SRPL Partner");
|
||||
|
||||
SuccessOrExit(error = ProcessZoneSection(aMessage, aDnsHeader, aOffset, zone));
|
||||
SuccessOrExit(error = ProcessZoneSection(aMessage, aMetadata));
|
||||
|
||||
if (FindOutstandingUpdate(aMessageInfo, aDnsHeader.GetMessageId()) != nullptr)
|
||||
if (FindOutstandingUpdate(aMetadata) != nullptr)
|
||||
{
|
||||
otLogInfoSrp("[server] drop duplicated SRP update request: messageId=%hu", aDnsHeader.GetMessageId());
|
||||
otLogInfoSrp("[server] Drop duplicated SRP update request: MessageId=%hu", aMetadata.mDnsHeader.GetMessageId());
|
||||
|
||||
// Silently drop duplicate requests.
|
||||
// This could rarely happen, because the outstanding SRP update timer should
|
||||
@@ -661,16 +677,16 @@ void Server::ProcessDnsUpdate(Message & aMessage,
|
||||
}
|
||||
|
||||
// Per 2.3.2 of SRP draft 6, no prerequisites should be included in a SRP update.
|
||||
VerifyOrExit(aDnsHeader.GetPrerequisiteRecordCount() == 0, error = kErrorFailed);
|
||||
VerifyOrExit(aMetadata.mDnsHeader.GetPrerequisiteRecordCount() == 0, error = kErrorFailed);
|
||||
|
||||
host = Host::New(GetInstance());
|
||||
host = Host::New(GetInstance(), aMetadata.mRxTime);
|
||||
VerifyOrExit(host != nullptr, error = kErrorNoBufs);
|
||||
SuccessOrExit(error = ProcessUpdateSection(*host, aMessage, aDnsHeader, zone, aOffset));
|
||||
SuccessOrExit(error = ProcessUpdateSection(*host, aMessage, aMetadata));
|
||||
|
||||
// Parse lease time and validate signature.
|
||||
SuccessOrExit(error = ProcessAdditionalSection(host, aMessage, aDnsHeader, aOffset));
|
||||
SuccessOrExit(error = ProcessAdditionalSection(host, aMessage, aMetadata));
|
||||
|
||||
HandleUpdate(aDnsHeader, *host, aMessageInfo);
|
||||
HandleUpdate(*host, aMetadata);
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
@@ -680,39 +696,35 @@ exit:
|
||||
host->Free();
|
||||
}
|
||||
|
||||
SendResponse(aDnsHeader, ErrorToDnsResponseCode(error), aMessageInfo);
|
||||
if (aMetadata.IsDirectRxFromClient())
|
||||
{
|
||||
SendResponse(aMetadata.mDnsHeader, ErrorToDnsResponseCode(error), *aMetadata.mMessageInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Error Server::ProcessZoneSection(const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t & aOffset,
|
||||
Dns::Zone & aZone) const
|
||||
Error Server::ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
char name[Dns::Name::kMaxNameSize];
|
||||
Dns::Zone zone;
|
||||
Error error = kErrorNone;
|
||||
char name[Dns::Name::kMaxNameSize];
|
||||
uint16_t offset = aMetadata.mOffset;
|
||||
|
||||
VerifyOrExit(aDnsHeader.GetZoneRecordCount() == 1, error = kErrorParse);
|
||||
VerifyOrExit(aMetadata.mDnsHeader.GetZoneRecordCount() == 1, error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
|
||||
// TODO: return `Dns::kResponseNotAuth` for not authorized zone names.
|
||||
VerifyOrExit(strcmp(name, GetDomain()) == 0, error = kErrorSecurity);
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, zone));
|
||||
aOffset += sizeof(zone);
|
||||
SuccessOrExit(error = aMessage.Read(offset, aMetadata.mDnsZone));
|
||||
offset += sizeof(Dns::Zone);
|
||||
|
||||
VerifyOrExit(zone.GetType() == Dns::ResourceRecord::kTypeSoa, error = kErrorParse);
|
||||
aZone = zone;
|
||||
VerifyOrExit(aMetadata.mDnsZone.GetType() == Dns::ResourceRecord::kTypeSoa, error = kErrorParse);
|
||||
aMetadata.mOffset = offset;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Server::ProcessUpdateSection(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Dns::Zone & aZone,
|
||||
uint16_t & aOffset) const
|
||||
Error Server::ProcessUpdateSection(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
@@ -722,16 +734,13 @@ Error Server::ProcessUpdateSection(Host & aHost,
|
||||
// 0. Enumerate over all Service Discovery Instructions before processing any other records.
|
||||
// So that we will know whether a name is a hostname or service instance name when processing
|
||||
// a "Delete All RRsets from a name" record.
|
||||
error = ProcessServiceDiscoveryInstructions(aHost, aMessage, aDnsHeader, aZone, aOffset);
|
||||
SuccessOrExit(error);
|
||||
SuccessOrExit(error = ProcessServiceDiscoveryInstructions(aHost, aMessage, aMetadata));
|
||||
|
||||
// 1. Enumerate over all RRs to build the Host Description Instruction.
|
||||
error = ProcessHostDescriptionInstruction(aHost, aMessage, aDnsHeader, aZone, aOffset);
|
||||
SuccessOrExit(error);
|
||||
SuccessOrExit(error = ProcessHostDescriptionInstruction(aHost, aMessage, aMetadata));
|
||||
|
||||
// 2. Enumerate over all RRs to build the Service Description Instructions.
|
||||
error = ProcessServiceDescriptionInstructions(aHost, aMessage, aDnsHeader, aZone, aOffset);
|
||||
SuccessOrExit(error);
|
||||
SuccessOrExit(error = ProcessServiceDescriptionInstructions(aHost, aMessage, aMetadata));
|
||||
|
||||
// 3. Verify that there are no name conflicts.
|
||||
VerifyOrExit(!HasNameConflictsWith(aHost), error = kErrorDuplicated);
|
||||
@@ -740,24 +749,23 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Server::ProcessHostDescriptionInstruction(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Dns::Zone & aZone,
|
||||
uint16_t aOffset) const
|
||||
Error Server::ProcessHostDescriptionInstruction(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const MessageMetadata &aMetadata) const
|
||||
{
|
||||
Error error;
|
||||
Error error;
|
||||
uint16_t offset = aMetadata.mOffset;
|
||||
|
||||
OT_ASSERT(aHost.GetFullName() == nullptr);
|
||||
|
||||
for (uint16_t numRecords = aDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
|
||||
for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
|
||||
{
|
||||
char name[Dns::Name::kMaxNameSize];
|
||||
Dns::ResourceRecord record;
|
||||
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, record));
|
||||
SuccessOrExit(error = aMessage.Read(offset, record));
|
||||
|
||||
if (record.GetClass() == Dns::ResourceRecord::kClassAny)
|
||||
{
|
||||
@@ -778,11 +786,11 @@ Error Server::ProcessHostDescriptionInstruction(Host & aHost,
|
||||
{
|
||||
Dns::AaaaRecord aaaaRecord;
|
||||
|
||||
VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
|
||||
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
|
||||
|
||||
SuccessOrExit(error = aHost.SetFullName(name));
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, aaaaRecord));
|
||||
SuccessOrExit(error = aMessage.Read(offset, aaaaRecord));
|
||||
VerifyOrExit(aaaaRecord.IsValid(), error = kErrorParse);
|
||||
|
||||
// Tolerate kErrorDrop for AAAA Resources.
|
||||
@@ -793,15 +801,15 @@ Error Server::ProcessHostDescriptionInstruction(Host & aHost,
|
||||
// We currently support only ECDSA P-256.
|
||||
Dns::Ecdsa256KeyRecord key;
|
||||
|
||||
VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, key));
|
||||
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
|
||||
SuccessOrExit(error = aMessage.Read(offset, key));
|
||||
VerifyOrExit(key.IsValid(), error = kErrorParse);
|
||||
|
||||
VerifyOrExit(aHost.GetKey() == nullptr || *aHost.GetKey() == key, error = kErrorSecurity);
|
||||
aHost.SetKey(key);
|
||||
}
|
||||
|
||||
aOffset += record.GetSize();
|
||||
offset += record.GetSize();
|
||||
}
|
||||
|
||||
// Verify that we have a complete Host Description Instruction.
|
||||
@@ -817,15 +825,14 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Server::ProcessServiceDiscoveryInstructions(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Dns::Zone & aZone,
|
||||
uint16_t aOffset) const
|
||||
Error Server::ProcessServiceDiscoveryInstructions(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const MessageMetadata &aMetadata) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
uint16_t offset = aMetadata.mOffset;
|
||||
|
||||
for (uint16_t numRecords = aDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
|
||||
for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
|
||||
{
|
||||
char serviceName[Dns::Name::kMaxNameSize];
|
||||
char instanceName[Dns::Name::kMaxNameSize];
|
||||
@@ -834,10 +841,10 @@ Error Server::ProcessServiceDiscoveryInstructions(Host & aHost
|
||||
Service * service;
|
||||
bool isSubType;
|
||||
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, serviceName, sizeof(serviceName)));
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, serviceName, sizeof(serviceName)));
|
||||
VerifyOrExit(Dns::Name::IsSubDomainOf(serviceName, GetDomain()), error = kErrorSecurity);
|
||||
|
||||
error = Dns::ResourceRecord::ReadRecord(aMessage, aOffset, ptrRecord);
|
||||
error = Dns::ResourceRecord::ReadRecord(aMessage, offset, ptrRecord);
|
||||
|
||||
if (error == kErrorNotFound)
|
||||
{
|
||||
@@ -849,10 +856,10 @@ Error Server::ProcessServiceDiscoveryInstructions(Host & aHost
|
||||
|
||||
SuccessOrExit(error);
|
||||
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, instanceName, sizeof(instanceName)));
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, instanceName, sizeof(instanceName)));
|
||||
|
||||
VerifyOrExit(ptrRecord.GetClass() == Dns::ResourceRecord::kClassNone ||
|
||||
ptrRecord.GetClass() == aZone.GetClass(),
|
||||
ptrRecord.GetClass() == aMetadata.mDnsZone.GetClass(),
|
||||
error = kErrorFailed);
|
||||
|
||||
// Check if the `serviceName` is a subtype with the name
|
||||
@@ -875,7 +882,7 @@ Error Server::ProcessServiceDiscoveryInstructions(Host & aHost
|
||||
// Ensure the same service does not exist already.
|
||||
VerifyOrExit(aHost.FindService(serviceName, instanceName) == nullptr, error = kErrorFailed);
|
||||
|
||||
service = aHost.AddNewService(serviceName, instanceName, isSubType);
|
||||
service = aHost.AddNewService(serviceName, instanceName, isSubType, aMetadata.mRxTime);
|
||||
VerifyOrExit(service != nullptr, error = kErrorNoBufs);
|
||||
|
||||
// This RR is a "Delete an RR from an RRset" update when the CLASS is NONE.
|
||||
@@ -886,23 +893,21 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Server::ProcessServiceDescriptionInstructions(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Dns::Zone & aZone,
|
||||
uint16_t & aOffset) const
|
||||
Error Server::ProcessServiceDescriptionInstructions(Host & aHost,
|
||||
const Message & aMessage,
|
||||
MessageMetadata &aMetadata) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
Error error = kErrorNone;
|
||||
uint16_t offset = aMetadata.mOffset;
|
||||
|
||||
for (uint16_t numRecords = aDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
|
||||
for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
|
||||
{
|
||||
Service::Description *desc;
|
||||
char name[Dns::Name::kMaxNameSize];
|
||||
Dns::ResourceRecord record;
|
||||
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, record));
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
|
||||
SuccessOrExit(error = aMessage.Read(offset, record));
|
||||
|
||||
if (record.GetClass() == Dns::ResourceRecord::kClassAny)
|
||||
{
|
||||
@@ -914,10 +919,10 @@ Error Server::ProcessServiceDescriptionInstructions(Host & aHo
|
||||
if (desc != nullptr)
|
||||
{
|
||||
desc->ClearResources();
|
||||
desc->mTimeLastUpdate = now;
|
||||
desc->mUpdateTime = aMetadata.mRxTime;
|
||||
}
|
||||
|
||||
aOffset += record.GetSize();
|
||||
offset += record.GetSize();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -927,11 +932,11 @@ Error Server::ProcessServiceDescriptionInstructions(Host & aHo
|
||||
char hostName[Dns::Name::kMaxNameSize];
|
||||
uint16_t hostNameLength = sizeof(hostName);
|
||||
|
||||
VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, srvRecord));
|
||||
aOffset += sizeof(srvRecord);
|
||||
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
|
||||
SuccessOrExit(error = aMessage.Read(offset, srvRecord));
|
||||
offset += sizeof(srvRecord);
|
||||
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, hostName, hostNameLength));
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, hostName, hostNameLength));
|
||||
VerifyOrExit(Dns::Name::IsSubDomainOf(name, GetDomain()), error = kErrorSecurity);
|
||||
VerifyOrExit(aHost.Matches(hostName), error = kErrorFailed);
|
||||
|
||||
@@ -940,35 +945,35 @@ Error Server::ProcessServiceDescriptionInstructions(Host & aHo
|
||||
|
||||
// Make sure that this is the first SRV RR for this service description
|
||||
VerifyOrExit(desc->mPort == 0, error = kErrorFailed);
|
||||
desc->mPriority = srvRecord.GetPriority();
|
||||
desc->mWeight = srvRecord.GetWeight();
|
||||
desc->mPort = srvRecord.GetPort();
|
||||
desc->mTimeLastUpdate = now;
|
||||
desc->mPriority = srvRecord.GetPriority();
|
||||
desc->mWeight = srvRecord.GetWeight();
|
||||
desc->mPort = srvRecord.GetPort();
|
||||
desc->mUpdateTime = aMetadata.mRxTime;
|
||||
}
|
||||
else if (record.GetType() == Dns::ResourceRecord::kTypeTxt)
|
||||
{
|
||||
VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
|
||||
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
|
||||
|
||||
desc = aHost.FindServiceDescription(name);
|
||||
VerifyOrExit(desc != nullptr, error = kErrorFailed);
|
||||
|
||||
aOffset += sizeof(record);
|
||||
SuccessOrExit(error = desc->SetTxtDataFromMessage(aMessage, aOffset, record.GetLength()));
|
||||
aOffset += record.GetLength();
|
||||
offset += sizeof(record);
|
||||
SuccessOrExit(error = desc->SetTxtDataFromMessage(aMessage, offset, record.GetLength()));
|
||||
offset += record.GetLength();
|
||||
}
|
||||
else
|
||||
{
|
||||
aOffset += record.GetSize();
|
||||
offset += record.GetSize();
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that all service descriptions on `aHost` are updated. Note
|
||||
// that `mTimeLastUpdate` on a new `Service::Description` is set to
|
||||
// that `mUpdateTime` on a new `Service::Description` is set to
|
||||
// `GetNow().GetDistantPast()`.
|
||||
|
||||
for (Service::Description &desc : aHost.mServiceDescriptions)
|
||||
{
|
||||
VerifyOrExit(desc.mTimeLastUpdate == now, error = kErrorFailed);
|
||||
VerifyOrExit(desc.mUpdateTime == aMetadata.mRxTime, error = kErrorFailed);
|
||||
|
||||
// Check that either both `mPort` and `mTxtData` are set
|
||||
// (i.e., we saw both SRV and TXT record) or both are default
|
||||
@@ -977,6 +982,8 @@ Error Server::ProcessServiceDescriptionInstructions(Host & aHo
|
||||
VerifyOrExit((desc.mPort == 0) == (desc.mTxtData == nullptr), error = kErrorFailed);
|
||||
}
|
||||
|
||||
aMetadata.mOffset = offset;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -987,32 +994,30 @@ bool Server::IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord)
|
||||
aRecord.GetTtl() == 0 && aRecord.GetLength() == 0;
|
||||
}
|
||||
|
||||
Error Server::ProcessAdditionalSection(Host * aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t & aOffset) const
|
||||
Error Server::ProcessAdditionalSection(Host *aHost, const Message &aMessage, MessageMetadata &aMetadata) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Dns::OptRecord optRecord;
|
||||
Dns::LeaseOption leaseOption;
|
||||
Dns::SigRecord sigRecord;
|
||||
char name[2]; // The root domain name (".") is expected.
|
||||
uint16_t offset = aMetadata.mOffset;
|
||||
uint16_t sigOffset;
|
||||
uint16_t sigRdataOffset;
|
||||
char signerName[Dns::Name::kMaxNameSize];
|
||||
uint16_t signatureLength;
|
||||
|
||||
VerifyOrExit(aDnsHeader.GetAdditionalRecordCount() == 2, error = kErrorFailed);
|
||||
VerifyOrExit(aMetadata.mDnsHeader.GetAdditionalRecordCount() == 2, error = kErrorFailed);
|
||||
|
||||
// EDNS(0) Update Lease Option.
|
||||
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, optRecord));
|
||||
SuccessOrExit(error = aMessage.Read(aOffset + sizeof(optRecord), leaseOption));
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
|
||||
SuccessOrExit(error = aMessage.Read(offset, optRecord));
|
||||
SuccessOrExit(error = aMessage.Read(offset + sizeof(optRecord), leaseOption));
|
||||
VerifyOrExit(leaseOption.IsValid(), error = kErrorFailed);
|
||||
VerifyOrExit(optRecord.GetSize() == sizeof(optRecord) + sizeof(leaseOption), error = kErrorParse);
|
||||
|
||||
aOffset += optRecord.GetSize();
|
||||
offset += optRecord.GetSize();
|
||||
|
||||
aHost->SetLease(leaseOption.GetLeaseInterval());
|
||||
aHost->SetKeyLease(leaseOption.GetKeyLeaseInterval());
|
||||
@@ -1029,22 +1034,22 @@ Error Server::ProcessAdditionalSection(Host * aHost,
|
||||
|
||||
// SIG(0).
|
||||
|
||||
sigOffset = aOffset;
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, sigRecord));
|
||||
sigOffset = offset;
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
|
||||
SuccessOrExit(error = aMessage.Read(offset, sigRecord));
|
||||
VerifyOrExit(sigRecord.IsValid(), error = kErrorParse);
|
||||
|
||||
sigRdataOffset = aOffset + sizeof(Dns::ResourceRecord);
|
||||
aOffset += sizeof(sigRecord);
|
||||
sigRdataOffset = offset + sizeof(Dns::ResourceRecord);
|
||||
offset += sizeof(sigRecord);
|
||||
|
||||
// TODO: Verify that the signature doesn't expire. This is not
|
||||
// implemented because the end device may not be able to get
|
||||
// the synchronized date/time.
|
||||
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, signerName, sizeof(signerName)));
|
||||
SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, signerName, sizeof(signerName)));
|
||||
|
||||
signatureLength = sigRecord.GetLength() - (aOffset - sigRdataOffset);
|
||||
aOffset += signatureLength;
|
||||
signatureLength = sigRecord.GetLength() - (offset - sigRdataOffset);
|
||||
offset += signatureLength;
|
||||
|
||||
// Verify the signature. Currently supports only ECDSA.
|
||||
|
||||
@@ -1052,9 +1057,11 @@ Error Server::ProcessAdditionalSection(Host * aHost,
|
||||
VerifyOrExit(sigRecord.GetTypeCovered() == 0, error = kErrorFailed);
|
||||
VerifyOrExit(signatureLength == Crypto::Ecdsa::P256::Signature::kSize, error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = VerifySignature(*aHost->GetKey(), aMessage, aDnsHeader, sigOffset, sigRdataOffset,
|
||||
SuccessOrExit(error = VerifySignature(*aHost->GetKey(), aMessage, aMetadata.mDnsHeader, sigOffset, sigRdataOffset,
|
||||
sigRecord.GetLength(), signerName));
|
||||
|
||||
aMetadata.mOffset = offset;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -1106,7 +1113,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Server::HandleUpdate(const Dns::UpdateHeader &aDnsHeader, Host &aHost, const Ip6::MessageInfo &aMessageInfo)
|
||||
void Server::HandleUpdate(Host &aHost, const MessageMetadata &aMetadata)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Host *existingHost;
|
||||
@@ -1133,33 +1140,29 @@ void Server::HandleUpdate(const Dns::UpdateHeader &aDnsHeader, Host &aHost, cons
|
||||
|
||||
if (aHost.FindService(service.GetServiceName(), service.GetInstanceName()) == nullptr)
|
||||
{
|
||||
Service *newService =
|
||||
aHost.AddNewService(service.GetServiceName(), service.GetInstanceName(), service.IsSubType());
|
||||
Service *newService = aHost.AddNewService(service.GetServiceName(), service.GetInstanceName(),
|
||||
service.IsSubType(), aMetadata.mRxTime);
|
||||
|
||||
VerifyOrExit(newService != nullptr, error = kErrorNoBufs);
|
||||
newService->mDescription.mTimeLastUpdate = TimerMilli::GetNow();
|
||||
newService->mIsDeleted = true;
|
||||
newService->mDescription.mUpdateTime = aMetadata.mRxTime;
|
||||
newService->mIsDeleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
if ((error == kErrorNone) && (mServiceUpdateHandler != nullptr))
|
||||
{
|
||||
CommitSrpUpdate(error, aDnsHeader, aHost, aMessageInfo);
|
||||
}
|
||||
else if (mServiceUpdateHandler != nullptr)
|
||||
{
|
||||
UpdateMetadata *update = UpdateMetadata::New(GetInstance(), aDnsHeader, &aHost, aMessageInfo);
|
||||
UpdateMetadata *update = UpdateMetadata::New(GetInstance(), aHost, aMetadata);
|
||||
|
||||
IgnoreError(mOutstandingUpdates.Add(*update));
|
||||
mOutstandingUpdatesTimer.StartAt(mOutstandingUpdates.GetTail()->GetExpireTime(), 0);
|
||||
mOutstandingUpdates.Push(*update);
|
||||
mOutstandingUpdatesTimer.FireAtIfEarlier(update->GetExpireTime());
|
||||
|
||||
otLogInfoSrp("[server] SRP update handler is notified (updatedId = %u)", update->GetId());
|
||||
mServiceUpdateHandler(update->GetId(), &aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommitSrpUpdate(kErrorNone, aDnsHeader, aHost, aMessageInfo);
|
||||
CommitSrpUpdate(error, aHost, aMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1263,25 +1266,29 @@ void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessag
|
||||
|
||||
Error Server::ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Error error;
|
||||
Dns::UpdateHeader dnsHeader;
|
||||
uint16_t offset = aMessage.GetOffset();
|
||||
return ProcessMessage(aMessage, TimerMilli::GetNow(), mLeaseConfig, &aMessageInfo);
|
||||
}
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(offset, dnsHeader));
|
||||
offset += sizeof(dnsHeader);
|
||||
Error Server::ProcessMessage(Message & aMessage,
|
||||
TimeMilli aRxTime,
|
||||
const LeaseConfig & aLeaseConfig,
|
||||
const Ip6::MessageInfo *aMessageInfo)
|
||||
{
|
||||
Error error;
|
||||
MessageMetadata metadata;
|
||||
|
||||
// Handles only queries.
|
||||
VerifyOrExit(dnsHeader.GetType() == Dns::UpdateHeader::Type::kTypeQuery, error = kErrorDrop);
|
||||
metadata.mOffset = aMessage.GetOffset();
|
||||
metadata.mRxTime = aRxTime;
|
||||
metadata.mLeaseConfig = aLeaseConfig;
|
||||
metadata.mMessageInfo = aMessageInfo;
|
||||
|
||||
switch (dnsHeader.GetQueryType())
|
||||
{
|
||||
case Dns::UpdateHeader::kQueryTypeUpdate:
|
||||
ProcessDnsUpdate(aMessage, aMessageInfo, dnsHeader, offset);
|
||||
break;
|
||||
default:
|
||||
error = kErrorDrop;
|
||||
break;
|
||||
}
|
||||
SuccessOrExit(error = aMessage.Read(metadata.mOffset, metadata.mDnsHeader));
|
||||
metadata.mOffset += sizeof(Dns::UpdateHeader);
|
||||
|
||||
VerifyOrExit(metadata.mDnsHeader.GetType() == Dns::UpdateHeader::Type::kTypeQuery, error = kErrorDrop);
|
||||
VerifyOrExit(metadata.mDnsHeader.GetQueryType() == Dns::UpdateHeader::kQueryTypeUpdate, error = kErrorDrop);
|
||||
|
||||
ProcessDnsUpdate(aMessage, metadata);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -1437,7 +1444,10 @@ const char *Server::AddressModeToString(AddressMode aMode)
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Server::Service
|
||||
|
||||
Server::Service *Server::Service::New(const char *aServiceName, Description &aDescription, bool aIsSubType)
|
||||
Server::Service *Server::Service::New(const char * aServiceName,
|
||||
Description &aDescription,
|
||||
bool aIsSubType,
|
||||
TimeMilli aUpdateTime)
|
||||
{
|
||||
void * buf;
|
||||
Service *service = nullptr;
|
||||
@@ -1445,7 +1455,7 @@ Server::Service *Server::Service::New(const char *aServiceName, Description &aDe
|
||||
buf = Heap::CAlloc(1, sizeof(Service));
|
||||
VerifyOrExit(buf != nullptr);
|
||||
|
||||
service = new (buf) Service(aDescription, aIsSubType);
|
||||
service = new (buf) Service(aDescription, aIsSubType, aUpdateTime);
|
||||
|
||||
if (service->mServiceName.Set(aServiceName) != kErrorNone)
|
||||
{
|
||||
@@ -1462,10 +1472,10 @@ void Server::Service::Free(void)
|
||||
Heap::Free(this);
|
||||
}
|
||||
|
||||
Server::Service::Service(Description &aDescription, bool aIsSubType)
|
||||
Server::Service::Service(Description &aDescription, bool aIsSubType, TimeMilli aUpdateTime)
|
||||
: mDescription(aDescription)
|
||||
, mNext(nullptr)
|
||||
, mTimeLastUpdate(TimerMilli::GetNow())
|
||||
, mUpdateTime(aUpdateTime)
|
||||
, mIsDeleted(false)
|
||||
, mIsSubType(aIsSubType)
|
||||
, mIsCommitted(false)
|
||||
@@ -1507,12 +1517,12 @@ TimeMilli Server::Service::GetExpireTime(void) const
|
||||
OT_ASSERT(!mIsDeleted);
|
||||
OT_ASSERT(!GetHost().IsDeleted());
|
||||
|
||||
return mTimeLastUpdate + Time::SecToMsec(mDescription.mLease);
|
||||
return mUpdateTime + Time::SecToMsec(mDescription.mLease);
|
||||
}
|
||||
|
||||
TimeMilli Server::Service::GetKeyExpireTime(void) const
|
||||
{
|
||||
return mTimeLastUpdate + Time::SecToMsec(mDescription.mKeyLease);
|
||||
return mUpdateTime + Time::SecToMsec(mDescription.mKeyLease);
|
||||
}
|
||||
|
||||
bool Server::Service::MatchesFlags(Flags aFlags) const
|
||||
@@ -1622,7 +1632,7 @@ Server::Service::Description::Description(Host &aHost)
|
||||
, mTxtData(nullptr)
|
||||
, mLease(0)
|
||||
, mKeyLease(0)
|
||||
, mTimeLastUpdate(TimerMilli::GetNow().GetDistantPast())
|
||||
, mUpdateTime(TimerMilli::GetNow().GetDistantPast())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1648,9 +1658,9 @@ void Server::Service::Description::TakeResourcesFrom(Description &aDescription)
|
||||
mWeight = aDescription.mWeight;
|
||||
mPort = aDescription.mPort;
|
||||
|
||||
mLease = aDescription.mLease;
|
||||
mKeyLease = aDescription.mKeyLease;
|
||||
mTimeLastUpdate = TimerMilli::GetNow();
|
||||
mLease = aDescription.mLease;
|
||||
mKeyLease = aDescription.mKeyLease;
|
||||
mUpdateTime = TimerMilli::GetNow();
|
||||
}
|
||||
|
||||
Error Server::Service::Description::SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
|
||||
@@ -1680,7 +1690,7 @@ exit:
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Server::Host
|
||||
|
||||
Server::Host *Server::Host::New(Instance &aInstance)
|
||||
Server::Host *Server::Host::New(Instance &aInstance, TimeMilli aUpdateTime)
|
||||
{
|
||||
void *buf;
|
||||
Host *host = nullptr;
|
||||
@@ -1688,7 +1698,7 @@ Server::Host *Server::Host::New(Instance &aInstance)
|
||||
buf = Heap::CAlloc(1, sizeof(Host));
|
||||
VerifyOrExit(buf != nullptr);
|
||||
|
||||
host = new (buf) Host(aInstance);
|
||||
host = new (buf) Host(aInstance, aUpdateTime);
|
||||
|
||||
exit:
|
||||
return host;
|
||||
@@ -1701,12 +1711,12 @@ void Server::Host::Free(void)
|
||||
Heap::Free(this);
|
||||
}
|
||||
|
||||
Server::Host::Host(Instance &aInstance)
|
||||
Server::Host::Host(Instance &aInstance, TimeMilli aUpdateTime)
|
||||
: InstanceLocator(aInstance)
|
||||
, mNext(nullptr)
|
||||
, mLease(0)
|
||||
, mKeyLease(0)
|
||||
, mTimeLastUpdate(TimerMilli::GetNow())
|
||||
, mUpdateTime(aUpdateTime)
|
||||
{
|
||||
mKey.Clear();
|
||||
}
|
||||
@@ -1742,12 +1752,12 @@ TimeMilli Server::Host::GetExpireTime(void) const
|
||||
{
|
||||
OT_ASSERT(!IsDeleted());
|
||||
|
||||
return mTimeLastUpdate + Time::SecToMsec(mLease);
|
||||
return mUpdateTime + Time::SecToMsec(mLease);
|
||||
}
|
||||
|
||||
TimeMilli Server::Host::GetKeyExpireTime(void) const
|
||||
{
|
||||
return mTimeLastUpdate + Time::SecToMsec(mKeyLease);
|
||||
return mUpdateTime + Time::SecToMsec(mKeyLease);
|
||||
}
|
||||
|
||||
const Server::Service *Server::Host::FindNextService(const Service *aPrevService,
|
||||
@@ -1780,7 +1790,10 @@ const Server::Service *Server::Host::FindNextService(const Service *aPrevService
|
||||
return service;
|
||||
}
|
||||
|
||||
Server::Service *Server::Host::AddNewService(const char *aServiceName, const char *aInstanceName, bool aIsSubType)
|
||||
Server::Service *Server::Host::AddNewService(const char *aServiceName,
|
||||
const char *aInstanceName,
|
||||
bool aIsSubType,
|
||||
TimeMilli aUpdateTime)
|
||||
{
|
||||
Service * service = nullptr;
|
||||
Service::Description *desc;
|
||||
@@ -1794,7 +1807,7 @@ Server::Service *Server::Host::AddNewService(const char *aServiceName, const cha
|
||||
mServiceDescriptions.Push(*desc);
|
||||
}
|
||||
|
||||
service = Service::New(aServiceName, *desc, aIsSubType);
|
||||
service = Service::New(aServiceName, *desc, aIsSubType, aUpdateTime);
|
||||
VerifyOrExit(service != nullptr);
|
||||
|
||||
mServices.Push(*service);
|
||||
@@ -1886,11 +1899,11 @@ Error Server::Host::MergeServicesAndResourcesFrom(Host &aHost)
|
||||
|
||||
otLogInfoSrp("[server] update host %s", GetFullName());
|
||||
|
||||
mAddresses = aHost.mAddresses;
|
||||
mKey = aHost.mKey;
|
||||
mLease = aHost.mLease;
|
||||
mKeyLease = aHost.mKeyLease;
|
||||
mTimeLastUpdate = TimerMilli::GetNow();
|
||||
mAddresses = aHost.mAddresses;
|
||||
mKey = aHost.mKey;
|
||||
mLease = aHost.mLease;
|
||||
mKeyLease = aHost.mKeyLease;
|
||||
mUpdateTime = TimerMilli::GetNow();
|
||||
|
||||
for (Service &service : aHost.mServices)
|
||||
{
|
||||
@@ -1906,15 +1919,15 @@ Error Server::Host::MergeServicesAndResourcesFrom(Host &aHost)
|
||||
|
||||
// Add/Merge `service` into the existing service or a allocate a new one
|
||||
|
||||
newService = (existingService != nullptr)
|
||||
? existingService
|
||||
: AddNewService(service.GetServiceName(), service.GetInstanceName(), service.IsSubType());
|
||||
newService = (existingService != nullptr) ? existingService
|
||||
: AddNewService(service.GetServiceName(), service.GetInstanceName(),
|
||||
service.IsSubType(), service.GetUpdateTime());
|
||||
|
||||
VerifyOrExit(newService != nullptr, error = kErrorNoBufs);
|
||||
|
||||
newService->mIsDeleted = false;
|
||||
newService->mIsCommitted = true;
|
||||
newService->mTimeLastUpdate = TimerMilli::GetNow();
|
||||
newService->mIsDeleted = false;
|
||||
newService->mIsCommitted = true;
|
||||
newService->mUpdateTime = TimerMilli::GetNow();
|
||||
|
||||
if (!service.mIsSubType)
|
||||
{
|
||||
@@ -1979,10 +1992,9 @@ exit:
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Server::UpdateMetadata
|
||||
|
||||
Server::UpdateMetadata *Server::UpdateMetadata::New(Instance & aInstance,
|
||||
const Dns::UpdateHeader &aHeader,
|
||||
Host * aHost,
|
||||
const Ip6::MessageInfo & aMessageInfo)
|
||||
Server::UpdateMetadata *Server::UpdateMetadata::New(Instance & aInstance,
|
||||
Host & aHost,
|
||||
const MessageMetadata &aMessageMetadata)
|
||||
{
|
||||
void * buf;
|
||||
UpdateMetadata *update = nullptr;
|
||||
@@ -1990,7 +2002,7 @@ Server::UpdateMetadata *Server::UpdateMetadata::New(Instance & aIn
|
||||
buf = Heap::CAlloc(1, sizeof(UpdateMetadata));
|
||||
VerifyOrExit(buf != nullptr);
|
||||
|
||||
update = new (buf) UpdateMetadata(aInstance, aHeader, aHost, aMessageInfo);
|
||||
update = new (buf) UpdateMetadata(aInstance, aHost, aMessageMetadata);
|
||||
|
||||
exit:
|
||||
return update;
|
||||
@@ -2001,18 +2013,20 @@ void Server::UpdateMetadata::Free(void)
|
||||
Heap::Free(this);
|
||||
}
|
||||
|
||||
Server::UpdateMetadata::UpdateMetadata(Instance & aInstance,
|
||||
const Dns::UpdateHeader &aHeader,
|
||||
Host * aHost,
|
||||
const Ip6::MessageInfo & aMessageInfo)
|
||||
Server::UpdateMetadata::UpdateMetadata(Instance &aInstance, Host &aHost, const MessageMetadata &aMessageMetadata)
|
||||
: InstanceLocator(aInstance)
|
||||
, mExpireTime(TimerMilli::GetNow() + kDefaultEventsHandlerTimeout)
|
||||
, mDnsHeader(aHeader)
|
||||
, mId(Get<Server>().AllocateId())
|
||||
, mHost(aHost)
|
||||
, mMessageInfo(aMessageInfo)
|
||||
, mNext(nullptr)
|
||||
, mExpireTime(TimerMilli::GetNow() + kDefaultEventsHandlerTimeout)
|
||||
, mDnsHeader(aMessageMetadata.mDnsHeader)
|
||||
, mId(Get<Server>().AllocateId())
|
||||
, mLeaseConfig(aMessageMetadata.mLeaseConfig)
|
||||
, mHost(aHost)
|
||||
, mIsDirectRxFromClient(aMessageMetadata.IsDirectRxFromClient())
|
||||
{
|
||||
if (aMessageMetadata.mMessageInfo != nullptr)
|
||||
{
|
||||
mMessageInfo = *aMessageMetadata.mMessageInfo;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Srp
|
||||
|
||||
+65
-59
@@ -358,7 +358,7 @@ public:
|
||||
uint8_t * mTxtData;
|
||||
uint32_t mLease; // The LEASE time in seconds.
|
||||
uint32_t mKeyLease; // The KEY-LEASE time in seconds.
|
||||
TimeMilli mTimeLastUpdate;
|
||||
TimeMilli mUpdateTime;
|
||||
};
|
||||
|
||||
enum Action : uint8_t
|
||||
@@ -371,18 +371,22 @@ public:
|
||||
kKeyLeaseExpired,
|
||||
};
|
||||
|
||||
static Service *New(const char *aServiceName, Description &aDescription, bool aIsSubType);
|
||||
static Service *New(const char * aServiceName,
|
||||
Description &aDescription,
|
||||
bool aIsSubType,
|
||||
TimeMilli aUpdateTime);
|
||||
|
||||
Service(Description &aDescription, bool aIsSubType);
|
||||
Service(Description &aDescription, bool aIsSubType, TimeMilli aUpdateTime);
|
||||
|
||||
void Free(void);
|
||||
bool MatchesFlags(Flags aFlags) const;
|
||||
void Log(Action aAction) const;
|
||||
void Free(void);
|
||||
bool MatchesFlags(Flags aFlags) const;
|
||||
const TimeMilli &GetUpdateTime(void) const { return mUpdateTime; }
|
||||
void Log(Action aAction) const;
|
||||
|
||||
Heap::String mServiceName;
|
||||
Description &mDescription;
|
||||
Service * mNext;
|
||||
TimeMilli mTimeLastUpdate;
|
||||
TimeMilli mUpdateTime;
|
||||
bool mIsDeleted : 1;
|
||||
bool mIsSubType : 1;
|
||||
bool mIsCommitted : 1;
|
||||
@@ -509,16 +513,19 @@ public:
|
||||
private:
|
||||
static constexpr uint16_t kMaxAddresses = OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM;
|
||||
|
||||
static Host *New(Instance &aInstance);
|
||||
static Host *New(Instance &aInstance, TimeMilli aUpdateTime);
|
||||
|
||||
explicit Host(Instance &aInstance);
|
||||
Host(Instance &aInstance, TimeMilli aUpdateTime);
|
||||
void Free(void);
|
||||
Error SetFullName(const char *aFullName);
|
||||
void SetKey(Dns::Ecdsa256KeyRecord &aKey);
|
||||
void SetLease(uint32_t aLease) { mLease = aLease; }
|
||||
void SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; }
|
||||
LinkedList<Service> &GetServices(void) { return mServices; }
|
||||
Service * AddNewService(const char *aServiceName, const char *aInstanceName, bool aIsSubType);
|
||||
Service * AddNewService(const char *aServiceName,
|
||||
const char *aInstanceName,
|
||||
bool aIsSubType,
|
||||
TimeMilli aUpdateTime);
|
||||
void RemoveService(Service *aService, RetainName aRetainName, NotifyMode aNotifyServiceHandler);
|
||||
void FreeAllServices(void);
|
||||
void FreeUnusedServiceDescriptions(void);
|
||||
@@ -536,7 +543,7 @@ public:
|
||||
Dns::Ecdsa256KeyRecord mKey;
|
||||
uint32_t mLease; // The LEASE time in seconds.
|
||||
uint32_t mKeyLease; // The KEY-LEASE time in seconds.
|
||||
TimeMilli mTimeLastUpdate;
|
||||
TimeMilli mUpdateTime;
|
||||
LinkedList<Service> mServices;
|
||||
LinkedList<Service::Description> mServiceDescriptions;
|
||||
};
|
||||
@@ -762,6 +769,21 @@ private:
|
||||
|
||||
static constexpr uint16_t kAnycastAddressModePort = 53;
|
||||
|
||||
// Metdata for a received SRP Update message.
|
||||
struct MessageMetadata
|
||||
{
|
||||
// Indicates whether the `Message` is received directly from a
|
||||
// client or from an SRPL partner.
|
||||
bool IsDirectRxFromClient(void) const { return (mMessageInfo != nullptr); }
|
||||
|
||||
Dns::UpdateHeader mDnsHeader;
|
||||
Dns::Zone mDnsZone;
|
||||
uint16_t mOffset;
|
||||
TimeMilli mRxTime;
|
||||
LeaseConfig mLeaseConfig;
|
||||
const Ip6::MessageInfo *mMessageInfo; // Set to `nullptr` when from SRPL.
|
||||
};
|
||||
|
||||
// This class includes metadata for processing a SRP update (register, deregister)
|
||||
// and sending DNS response to the client.
|
||||
class UpdateMetadata : public InstanceLocator, public LinkedListEntry<UpdateMetadata>
|
||||
@@ -769,30 +791,28 @@ private:
|
||||
friend class LinkedListEntry<UpdateMetadata>;
|
||||
|
||||
public:
|
||||
static UpdateMetadata * New(Instance & aInstance,
|
||||
const Dns::UpdateHeader &aHeader,
|
||||
Host * aHost,
|
||||
const Ip6::MessageInfo & aMessageInfo);
|
||||
static UpdateMetadata * New(Instance &aInstance, Host &aHost, const MessageMetadata &aMessageMetadata);
|
||||
void Free(void);
|
||||
TimeMilli GetExpireTime(void) const { return mExpireTime; }
|
||||
const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; }
|
||||
ServiceUpdateId GetId(void) const { return mId; }
|
||||
Host & GetHost(void) { return *mHost; }
|
||||
const LeaseConfig & GetLeaseConfig(void) const { return mLeaseConfig; }
|
||||
Host & GetHost(void) { return mHost; }
|
||||
const Ip6::MessageInfo & GetMessageInfo(void) const { return mMessageInfo; }
|
||||
bool IsDirectRxFromClient(void) const { return mIsDirectRxFromClient; }
|
||||
bool Matches(ServiceUpdateId aId) const { return mId == aId; }
|
||||
|
||||
private:
|
||||
UpdateMetadata(Instance & aInstance,
|
||||
const Dns::UpdateHeader &aHeader,
|
||||
Host * aHost,
|
||||
const Ip6::MessageInfo & aMessageInfo);
|
||||
UpdateMetadata(Instance &aInstance, Host &aHost, const MessageMetadata &aMessageMetadata);
|
||||
|
||||
UpdateMetadata * mNext;
|
||||
TimeMilli mExpireTime;
|
||||
Dns::UpdateHeader mDnsHeader;
|
||||
ServiceUpdateId mId; // The ID of this service update transaction.
|
||||
Host * mHost; // The host will be updated. The UpdateMetadata has no ownership of this host.
|
||||
Ip6::MessageInfo mMessageInfo; // The message info of the DNS update request.
|
||||
UpdateMetadata * mNext;
|
||||
LeaseConfig mLeaseConfig; // Lease config to use when processing the message.
|
||||
Host & mHost; // The `UpdateMetadata` has no ownership of this host.
|
||||
Ip6::MessageInfo mMessageInfo; // Valid when `mIsDirectRxFromClient` is true.
|
||||
bool mIsDirectRxFromClient;
|
||||
};
|
||||
|
||||
void Start(void);
|
||||
@@ -810,24 +830,21 @@ private:
|
||||
|
||||
ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; }
|
||||
|
||||
void CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata);
|
||||
void CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata);
|
||||
void CommitSrpUpdate(Error aError,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
Host & aHost,
|
||||
const Ip6::MessageInfo & aMessageInfo);
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Ip6::MessageInfo * aMessageInfo,
|
||||
const LeaseConfig & aLeaseConfig);
|
||||
Error ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void ProcessDnsUpdate(Message & aMessage,
|
||||
const Ip6::MessageInfo & aMessageInfo,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t aOffset);
|
||||
Error ProcessUpdateSection(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Dns::Zone & aZone,
|
||||
uint16_t & aOffset) const;
|
||||
Error ProcessAdditionalSection(Host * aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t & aOffset) const;
|
||||
Error ProcessMessage(Message & aMessage,
|
||||
TimeMilli aRxTime,
|
||||
const LeaseConfig & aLeaseConfig,
|
||||
const Ip6::MessageInfo *aMessageInfo);
|
||||
void ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata);
|
||||
Error ProcessUpdateSection(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const;
|
||||
Error ProcessAdditionalSection(Host *aHost, const Message &aMessage, MessageMetadata &aMetadata) const;
|
||||
Error VerifySignature(const Dns::Ecdsa256KeyRecord &aKey,
|
||||
const Message & aMessage,
|
||||
Dns::UpdateHeader aDnsHeader,
|
||||
@@ -835,29 +852,18 @@ private:
|
||||
uint16_t aSigRdataOffset,
|
||||
uint16_t aSigRdataLength,
|
||||
const char * aSignerName) const;
|
||||
Error ProcessZoneSection(const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t & aOffset,
|
||||
Dns::Zone & aZone) const;
|
||||
Error ProcessHostDescriptionInstruction(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Dns::Zone & aZone,
|
||||
uint16_t aOffset) const;
|
||||
Error ProcessServiceDiscoveryInstructions(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Dns::Zone & aZone,
|
||||
uint16_t aOffset) const;
|
||||
Error ProcessServiceDescriptionInstructions(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
const Dns::Zone & aZone,
|
||||
uint16_t & aOffset) const;
|
||||
Error ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const;
|
||||
Error ProcessHostDescriptionInstruction(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const MessageMetadata &aMetadata) const;
|
||||
Error ProcessServiceDiscoveryInstructions(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const MessageMetadata &aMetadata) const;
|
||||
Error ProcessServiceDescriptionInstructions(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const;
|
||||
|
||||
static bool IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord);
|
||||
|
||||
void HandleUpdate(const Dns::UpdateHeader &aDnsHeader, Host &aHost, const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleUpdate(Host &aHost, const MessageMetadata &aMetadata);
|
||||
void AddHost(Host &aHost);
|
||||
void RemoveHost(Host *aHost, RetainName aRetainName, NotifyMode aNotifyServiceHandler);
|
||||
bool HasNameConflictsWith(Host &aHost) const;
|
||||
@@ -876,7 +882,7 @@ private:
|
||||
void HandleOutstandingUpdatesTimer(void);
|
||||
|
||||
void HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError);
|
||||
const UpdateMetadata *FindOutstandingUpdate(const Ip6::MessageInfo &aMessageInfo, uint16_t aDnsMessageId);
|
||||
const UpdateMetadata *FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const;
|
||||
static const char * AddressModeToString(AddressMode aMode);
|
||||
|
||||
Ip6::Udp::Socket mSocket;
|
||||
|
||||
Reference in New Issue
Block a user