Commit Graph

38 Commits

Author SHA1 Message Date
Abtin Keshavarzian b2093f4f9e [dns] check for null character in read label (#13187)
This commit updates `Name::LabelIterator::ReadLabel()` to explicitly
check that the read label from the message does not contain any embedded
`kNullChar` (`\0`) characters. It uses `StringLength()` to verify that
the length of the string matches the expected label length. If a null
character is found before the end of the label, `kErrorParse` is
returned to prevent potential string truncation issues or
misinterpretation of the label name.

This broader check replaces a recent fix in `PtrRecord::ReadPtrName()`
from #13183 which only verified that the first label was not empty
or malformed by checking for a single-character label with a null
byte. By enforcing this validation centrally at the `ReadLabel()`
level, we now ensure that labels of any length are properly
protected against embedded null characters across all DNS record
types.
2026-06-03 14:55:20 -07:00
Abtin Keshavarzian 9d95a19e52 [tests] use constexpr for constants in unit tests (#13145)
This commit refactors various unit tests to use `constexpr` for
defining constants instead of anonymous `enum` types.

Using `constexpr` is the modern and preferred approach in C++, as it
provides explicit types for constants and improves code clarity and
type safety.
2026-05-25 19:39:27 -07:00
Abtin Keshavarzian d0237f5e91 [dns] add MatchesKey() to Dns::TxtEntry (#12579)
This commit adds `MatchesKey()` method to `Dns::TxtEntry` class to
check if the entry's key matches a given key string using a
case-insensitive string comparison.

The new method properly handles the case where the entry's key is
`nullptr` (which can happen when the key is longer than the
recommended max length). It simplifies the TXT entry parsing logic in
`BorderAgent` and `Trel::PeerDiscoverer`.

The unit tests for `Dns::TxtEntry` are also updated to verify the new
method.
2026-02-27 18:55:35 -06:00
Abtin Keshavarzian cfe2999c94 [dns] update Name::ValidateName() for max-length names (#12127)
`ValidateName()` did not correctly handle names that were exactly the
maximum allowed length (`kMaxNameLength`). A name of this length is
only valid if it ends with a trailing dot. Otherwise, when encoded,
the added root label causes the encoded name to exceed the
`kMaxEncodedLength` of 255 bytes.

This commit updates `ValidateName()` to enforce that any name with
length equal to `kMaxNameLength` must end with a dot character.

It also updates the `TestDnsName` unit test to verify this corrected
behavior, ensuring `ValidateName()` and `AppendName()` handle such
names consistently.
2025-11-08 11:25:23 -08:00
Abtin Keshavarzian 99f510a16c [mdns] add validation for DNS names in mDNS APIs (#12039)
This commit adds `Dns::Name::ValidateName()` and `ValidateLabel()`
helper methods to validate a DNS name or label.

These methods are used at the entry of the mDNS `Register*()` and
`Unregister*()` public APIs to validate the provided host, service,
and key names. This prevents issues with malformed names and improves
the robustness of the mDNS module.

Includes unit tests for the new validation methods.
2025-10-17 21:25:42 -07:00
Abtin Keshavarzian 2e73358f9d [dns] introduce DecompressRecordData() and use it in mDNS (#11408)
This commit updates the mDNS `RecordQuerier` to handle record types
where the RDATA contains one or more potentially compressed DNS
names. For these types, the reported record data is now decompressed
to include the full DNS names. This enhancement applies to the
following record types: NS, CNAME, SOA, PTR, MX, RP, AFSDB, RT, PX,
SRV, KX, DNAME, and NSEC.

To achieve this, a helper `ResourceRecord::DecompressRecordData()`
method is introduced. This method uses a "recipe" formula specific
to each supported record type. The recipe defines the number of
prefix bytes before the first embedded name, the number of DNS
names, and the minimum number of suffix bytes after the names. A
common implementation then uses this recipe to parse and decompress
the RDATA. This approach makes the implementation flexible and allows
for easier addition of new record types and formats in the future.

Unit test `test_dns` is updated to validate the newly added method.
2025-04-21 14:29:09 -07:00
Abtin Keshavarzian 8e3f51da84 [dns] add checks for multi-label looped compressed DNS names (#10215)
This commit enhances `Dns::Name` to detect and handle cases where a
compressed DNS name contains a loop spanning multiple labels. The
`test_dns` unit test has been updated to include test cases for these
invalid names.
2024-05-08 18:56:02 -07:00
Abtin Keshavarzian be7d36e4ff [dns] add Name::StripName() and support in-place ExtractLabels() (#10037)
- Updates `Dns::Name::ExtractLabels()` for in-place label extraction,
  optimizing string operations.
- Introduces `Name::StripName()` to efficiently remove a suffix name
  from a DNS name in place.
- Updates and simplifies unit tests `test_dns` to validate new
  functionality.
2024-04-17 15:21:16 -07:00
Abtin Keshavarzian 666a9bd076 [dns] add Name::ComapreMultipleLabels() and update Matches() (#9744)
This commit introduces a new method, `Name::CompareMultipleLabels()`,
to efficiently parse and compare multiple DNS name labels directly
from a message. This is then used to optimize `Name::Matches()`
eliminating the need to read the entire name into a separate buffer.

This commit also updates `Name::Matches()` method to treat the
first label as a single label allowing it to include dot character
(which is useful for service instance label).

Additionally, `test_dns` unit test is updated to validate the
functionality of the new methods.
2023-12-28 18:26:35 -08:00
Abtin Keshavarzian 3f99b118d4 [dns] clarify trailing dot in Name::ExtractLabels() (#9743)
This commit updates `ExtractLabels()` documentation to clarify that
name and suffix name can include or exclude the trailing dot but both
inputs must follow the same style. It also updates `test_dns` unit
test to validate this behavior.
2023-12-27 22:10:53 -08:00
Abtin Keshavarzian 51a682ec0e [dns] add Name::Matches() to compare DNS names (#9734)
This commit adds `Name::Matches()` method which compares a `Name`
instance (which can be from a C string or encoded in a `Message`)
with a given set of labels and domain name strings. This method
allows the caller to specify name components separately, enabling
scenarios like comparing "service instance name" with separate
instance label, service type, and domain strings. Unit test
`test_dns` is also updated to validate the behavior of the newly
added method.
2023-12-20 14:20:58 -08:00
Abtin Keshavarzian a492d04a31 [dns-types] add template variants of reading DNS names or labels (#9720)
This commit introduces template variants for `ReadName()` and other
related methods, allowing flexible reading of DNS names and labels
from messages into a given array buffer. This simplifies the code and
improves readability.

Additionally, this commit defines new types, `Dns::Name::Buffer` and
`Dns::Name::LabelBuffer`, as arrays of char with fixed sizes to hold
DNS names and labels, respectively.
2023-12-19 10:45:46 -08:00
Abtin Keshavarzian 657b973bb2 [dns] support longer key length in otDnsTxtEntryIterator (#9616)
This commit introduces `OT_DNS_TXT_KEY_ITER_MAX_LENGTH` with a value
of `64` to represent the maximum TXT data key length supported by
`otDnsTxtEntryIterator`. We intentionally set this value higher than
the recommended maximum key length of `9` (as specified in RFC 6763
section 6.4) to enable the parsing of TXT data when longer keys are
employed.
2023-11-19 18:47:21 -08:00
Abtin Keshavarzian 1528c8831d [core] define core/instance folder for instance modules (#9561)
This commit moves the `instance` module to a newly added folder
`core/instance` (from `core/common`.  Header file `extension.hpp`
and its example is also moved to the same folder.
2023-10-26 05:08:24 -07:00
Abtin Keshavarzian 7e32165bee [dnssd-server] determine query type & simplify processing of query name (#9349)
This commit simplifies and enhances the DNSSD Server implementation:

- A new method, `ParseQuestions()`, has been added to process the
  questions in a received `Request` message and determine the
  `QueryType`.

- The processing and appending of the query DNS name has been
  simplified. The query name is now read and copied label by label
  from the `Request` message into the `Response`. When matching the
  name against SRP entries, the names are compared with the query
  name directly as it is encoded in the `Response` message using the
  `Dns::Name::CompareName()` method. This approach is more flexible
  and simpler, and it works for all query types and name formats,
  including service instance names where the first label can itself
  contain a dot (`.`) character. This simplification allows us to
  remove the helper functions that were previously used to parse the
  query name and deal with the ambiguity that arises when service
  instance names are read as strings of dot-separated labels.

- The management of offsets for DNS name compression has also been
  simplified. A new method, `Response::ParseQueryName()`, has been
  added to validate the query name (e.g., that it contains the
  correct domain) and determine all offsets.

- The `ResolveBySrp()` method has also been simplified using query
  type and the newly added flavors of `Append{Ptr/Srv/Txt}Record()`
  methods.

- Finally, this commit adds the `Dns::Name::ExtractLabels()` helper
  method, which extracts label(s) from a full DNS name string by
  first checking that it contains a given suffix name (e.g., the
  suffix name can be a domain name or a service name) and then
  removing it, returning the label(s).
2023-08-15 12:12:02 -07:00
Abtin Keshavarzian 0cc1de7b5a [srp-server] allow service instance label with dot character (#9198)
This commit updates the `Srp::Server` class to correctly handle the
case where a service is registered with a dot character in its
service instance name. The first label in a service instance name is
intended as a user-friendly name and can contain dot characters
(it has fewer restrictions than other labels in a DNS name).

In particular, this commit contains the following changes:
- The `PtrRecords::ReadPtrName()` method is used in `Srp::Server` to
  read and validate the first label and the rest of the labels
  separately. This also validates the format of the parsed PTR
  record.
- The `Service::Description` class now remembers the instance label in
  addition to the full instance name. This allows the instance label
  to be easily retrieved.
- The `Dns::Name::ReadName()` method is updated to only verify that
  the labels after the first label do not contain any dot characters.
  This allows it to be used to read instance service names.
- The tests are updated to validate the behavior of the SRP server
  when the instance label contains a dot character.
2023-06-26 12:55:45 -07:00
Zhanglong Xia f64b7cc73c [test] add code spell check and correct wrong spelling (#9066) 2023-05-22 18:04:09 -07:00
Song GUO 852d076f00 [dnssd] support forwarding DNS queries to platform upstream (#8668)
This commit adds a set of APsI for forwarding a DNS query to the
upstream DNS server via platform API and a posix platform
implementation.

This feature is disabled by default, and this PR adds a `dns server
upstream {enable|disable}` command CLI for enabling and disabling this
feature.

Tests will be added after ot-br-posix adds related support.
2023-02-21 21:15:03 -08:00
Jonathan Hui 9c467a23ae [clang-format] apply v14 changes (#8490) 2022-12-07 16:23:20 -08:00
Abtin Keshavarzian d3e00fbd28 [dns] allow partial read of TXT data and add config for max size in CLI (#8232)
This commit updates `Dns::Client` so that when reading service info
`otDnsServiceInfo` if the received TXT data does not fit in the given
buffer, it is read partially. A new field `mTxtDataTruncated` is added
in `otDnsServiceInfo` to indicate that TXT data was not fully read.

This commit also updates `dns` related commands in CLI so to output
the partially read TXT data and add a new config specifying the max
TXT data size used by CLI.
2022-10-05 15:10:28 -07:00
Abtin Keshavarzian 7ec658e47a [common] add GetArrayLength() and GetArrayEnd() (#7413)
This commit adds two inline template functions to get the length of an
array and a pointer to the end of the array. These functions replace
similar macros that were used with OT core modules. The template
functions are safer to use since they would perform type checking at
compile time. The functions validate that the input variable is
indeed an array and unlike the macros they will not work with a
pointer variable.
2022-02-14 14:03:23 -08:00
Abtin Keshavarzian 16798fdcc0 [message] simplify method for allocating new message from pool (#7210)
This commit removes different `MessagePool` methods that can be used
to allocate a new message  and combines them into one `Allocate()`
method which uses `Message::Settings`. The `Message::Settings` is
also updated to provide new constructor initializing it with a given
message priority only.
2021-11-29 13:46:07 -08:00
Abtin Keshavarzian e16261aa6c [dns] change Dns::Name::CompareName/Label() to be case-insensitive (#7189)
This commit changes the `Dns::Name::CompareName/Label()` methods to
perform case-insensitive string comparison. This is realized by
adding a new flavor of `Data::MatchesBytesIn()` which accepts a
`ByteMatcher` function pointer. This allows the caller to relax the
definition of a match and how the bytes are compared. `Message` class
methods that compare bytes are also updated to allow `ByteMatcher` as
an input parameter. This commit also updates the unit test `test_dns`
to cover the new method and behaviors.
2021-11-23 16:31:18 -08:00
Abtin Keshavarzian 56ca28882a [dns] TxtEntry::AppendEntries() to append into a buffer (#7176)
This commit adds new flavor of `Dns::TxtEntry::AppendEntries()` to
encode and append TXT record entries in a data buffer (in addition to
existing one which appends to a `Message`). `Appender` class is used
in the underlying implementation . This commit also updates
`test_dns` unit test to validate newly added method.
2021-11-22 21:41:28 -08:00
Abtin Keshavarzian 57d072d352 [test] enhance {Verify/Success}OrQuit() and their use in unit test (#6764)
This commit updates `VerifyOrQuit()` and `SuccessOrQuit()` macros to
include the failed condition in the error message that is printed on
a failure (in addition to function name and line number where the
error happened). This commit also changes the second parameter
(`aMessage`) to in these macros to be optional.

This commit also updates unit tests to remove the second `aMessage`
string in cases where the failure can be inferred from the condition
itself.
2021-06-28 11:38:10 -07:00
Abtin Keshavarzian 45bd0a0851 [dns] adding Name::AppendTo() to copy DNS name from one message to another (#6365)
This commit adds `AppendTo()` method in `Dns::Name` class. This method
allows appending an already encoded name from one message to another.
This is performed by directly copying labels one by one between the
messages and does not require an intermediate buffer to read and store
the labels or the full name. This commit also updates `test_dns` unit
test to cover the behavior of the newly added method.
2021-03-30 18:49:17 -07:00
Abtin Keshavarzian 7dca56e982 [error] add 'ot::Error' and 'kError{Name}' for use by core modules (#6237)
This commit adds a new core header files `common/error.hpp` which
defines `ot::Error` (mirroring `otError`) and `kError{Name}` constants
(mirroring the public `OT_ERROR_{NAME}` definitions). The new (C++
style) definitions are used by core modules. This commit also moves
`otThreadErrorToString()` (from `logging.hpp` to `error.hpp`) and
renames it to `ErrorToString()` which is used as the internal (to
core) function to covert an `Error` to a string.
2021-03-15 21:07:07 -07:00
Abtin Keshavarzian 95b2a8b98f [dns] rename to 'dns_types.hpp' (#6193)
This commit renames the DNS helper module from `dns_header` to
`dns_types`.
2021-02-22 23:26:54 -08:00
Abtin Keshavarzian 14ef4e4082 [dns-header] add common TXT record entry parsing API (#6157)
This commit adds a new public `ot` API for parsing an encoded DNS TXT
record data into `TxtEntry` key/value pairs. It also updates the TXT
data iterator model used for going through all TXT entries. The new
iterator definition provides a small buffer to store the key string.
This helps simplify the definition of `otDnsTxtEntry` to use
null-terminated C string for the key. The new parsing APIs are used in
CLI module.

This commit also fixes an issue with `TxtEntry::AppendEntries()` using
incorrect value for the key length.

Finally, this commit adds a test covering the behavior of all
`TxtEntry` related methods (encoding and parsing TXT data) in the unit
test `test_dns`.
2021-02-19 16:17:35 -08:00
Abtin Keshavarzian 7084422a0e [dns-client] service discovery (DNS-SD) support and enhancements (#6116)
This commit re-designs the `Dns::Client` module enhancing the address
resolution implementation and also adding support for DNS-Based
Service Discovery (DNS-SD).

With regards to address resolution query the new model relaxes the
requirements of the public OT APIs such that caller does not need to
persist the query info (e.g., the host name string buffer can be a
temporary variable and does not need to persist during the query) and
it is all managed by the `Dns::Client` core implementation itself. The
new model also supports the case where the response contains multiple
IPv6 addresses providing new APIs to allow the user to iterate through
the list of addresses and retrieve them one by one.

The implementation also handles the case where the DNS query response
contains CNAME record mapping the queried host name to a canonical
name for which a list of addresses are then provided.

The core implementation is also simplified, instead of cloning a query
message and saving it for possible retx, the new code saves the query
related info from which it can re-construct the query message for retx
if/when needed.

This commit also adds support for DNS-SD in `Dns::Client`. The config
`OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE` can be used to
disable service discovery feature. The implementation supports
"service instance enumeration" which is referred to as "browsing" and
"service instance resolution". Callbacks are used to notify the user
when a response is received. In the callback a pointer to an opaque
response object is given to the user which can then be used with the
new set of APIs to get more info about the response, such as the list
of discovered service instances or more details about a specific
service instance (e.g., port number, host name and its address) or
iterate through address lists. This provides a flexible and scalable
solution to handle larger lists in the response without adding memory
overhead in the implementation.
2021-02-12 11:27:11 -08:00
Abtin Keshavarzian b5b6cf1766 [dns-header] new helper method to find i-th record matching name and type (#6124)
This commit adds a new template helper method in `ResoureRecord` to
search in a given message starting from a given offset and up to a
maximum given number of records, for the i-th occurrence of a specific
record (of given type with a matching record name). If found, it reads
the record from the message into a given record object.

This commit also updates the unit test `test_dns` to cover the behavior of
newly added helper method.
2021-02-01 22:12:05 -08:00
kangping 4bb22d78de [dns] match DNS name with specific domain (#6114)
This commit adds:
- a new method Dns::Name::IsSubDomainOf that matches a DNS name with
given domain. This is useful for SRP and DNS-SD server to verify if a
RR is in our authorized domain.
- domain checks for names in a SRP update to the SRP server.
2021-01-29 07:22:09 -08:00
Abtin Keshavarzian c03458433e [dns-name] allow 'Dns::Name' to be given as string or from message (#6117)
This commit allows `Dns::Name` instances to be created which can be
empty or given as a string (a dot '.' separated sequence of labels) or
from a message at a given offset (i.e., name is already encoded in a
message). `CompareName` and `FindRecord()` helper methods are updated
to allow the new `Dns::Name` type to be used when comparing/ searching
for a name.
2021-01-28 14:27:17 -08:00
Abtin Keshavarzian 9ea89ca204 [dns-header] helper methods to parse/find/read record(s) in a message (#6097)
This commit adds new helper methods in `ResourceRecord` class.
`ParseRecords()` parses and skips over a given number of resource
records in a message. `FindRecord()` searches in a given message to
find the first resource record matching a given record name. And
`ReadRecord<RecordType>()` tries to read a matching resource record
(of a given type) from a message. If the record type does not match
the type, it skips over the record. This commit also adds methods in
`PtrRecord`, `SrvRecord`, `SigRecord` and `TxtRecord` to parse and
read the data fields such as PTR name, host name, signer name and
TXT data.

This commit updates the DNS unit test to add a detailed new test
constructing and parsing a DNS message (covering the behavior of
the newly added and some of the existing methods).
2021-01-25 21:16:39 -08:00
Abtin Keshavarzian 57bc0a3396 [dns-header] new methods to compare label/name from message (#6078)
This commit adds new helper methods in `Dns::Name` to parse and
compare a single name label `CompareLabel()` or an entire name
`ComapareName()` from a given message with a given string. Another
flavor of `CompareName()` compares the names read from two different
messages (or same message at different offsets). The name checks are
performed in place (without reading/copying the content from the
messages) and the implementation handles compressed names.

Unit test `test_dns` is updated to verify behavior of newly added
methods.
2021-01-24 21:45:31 -08:00
Simon Lin 6ee13b7a8d [dns] fix dns failed to append names of length 255 (#6088) 2021-01-23 08:50:06 -08:00
Abtin Keshavarzian e12178a256 [dns-name] require message offset to point to DNS header (#6101)
This commit contains two changes in `Dns::Name` class. When reading or
parsing names/labels from a `Message`, we require that the message
offset (i.e., `aMessage.GetOffset()`) to be set by the caller to point
to the start of the DNS header in the message. This is then used to
decode compressed DNS names. This change helps simplify the code and
removes the need to pass `aHeaderOffset` as a separate parameter. The
second change is to the `ParseName()` implementation which now always
goes through and parses the entire compressed name before returning.
This ensures that we correctly detect invalid compressed names when
parsing the name in a message.
2021-01-22 17:38:56 -08:00
Abtin Keshavarzian 73126f7099 [dns] add helper methods to append/parse DNS names (#5922)
This commit adds `Dns::Name` type which provides a set of helper
methods to encode/decode DNS names. `AppendName()` method encodes and
appends a full name (e.g., "test.example.com") to a message. Other
helper methods enable appending labels (or groups of labels) and/or
constructing a compressed name (using pointer labels). `ParseName()`
method parses and skips over a full name in a message. `ReadLabel()`
method reads labels one by one and works independently of whether the
encoded name is compressed or not. `ReadName()` method read an entire
name from message. The new methods are used in `Dns::Client`.

This commit also add a unit test `test-dns` covering the behavior of
the newly added helper methods.

Finally, this commit adds few helper methods in `ResourceRecords` to
get the size and check the type of a DNS record.
2020-12-08 12:20:19 -08:00