1 /*
2  *  Copyright (c) 2024, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * @brief
32  *   This file includes the mDNS related APIs.
33  *
34  */
35 
36 #ifndef OPENTHREAD_MULTICAST_DNS_H_
37 #define OPENTHREAD_MULTICAST_DNS_H_
38 
39 #include <stdint.h>
40 
41 #include <openthread/error.h>
42 #include <openthread/instance.h>
43 #include <openthread/ip6.h>
44 #include <openthread/platform/dnssd.h>
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 /**
51  * @addtogroup api-mdns
52  *
53  * @brief
54  *   This module includes APIs for Multicast DNS (mDNS).
55  *
56  * @{
57  *
58  * The mDNS APIs are available when the mDNS support `OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE` is enabled and the
59  * `OPENTHREAD_CONFIG_MULTICAST_DNS_PUBLIC_API_ENABLE` is also enabled.
60  *
61  */
62 
63 /**
64  * Represents a request ID (`uint32_t` value) for registering a host, a service, or a key service.
65  *
66  */
67 typedef otPlatDnssdRequestId otMdnsRequestId;
68 
69 /**
70  * Represents the callback function to report the outcome of a host, service, or key registration request.
71  *
72  * The outcome of a registration request is reported back by invoking this callback with one of the following `aError`
73  * inputs:
74  *
75  * - `OT_ERROR_NONE` indicates registration was successful.
76  * - `OT_ERROR_DUPLICATED` indicates a name conflict while probing, i.e., name is claimed by another mDNS responder.
77  *
78  * See `otMdnsRegisterHost()`, `otMdnsRegisterService()`, and `otMdnsRegisterKey()` for more details about when
79  * the callback will be invoked.
80  *
81  * @param[in] aInstance     The OpenThread instance.
82  * @param[in] aRequestId    The request ID.
83  * @param[in] aError        Error indicating the outcome of request.
84  *
85  */
86 typedef otPlatDnssdRegisterCallback otMdnsRegisterCallback;
87 
88 /**
89  * Represents the callback function to report a detected name conflict after successful registration of an entry.
90  *
91  * If a conflict is detected while registering an entry, it is reported through the provided `otMdnsRegisterCallback`.
92  * The `otMdnsConflictCallback` is used only when a name conflict is detected after an entry has been successfully
93  * registered.
94  *
95  * A non-NULL @p aServiceType indicates that conflict is for a service entry. In this case @p aName specifies the
96  * service instance label (treated as as a single DNS label and can potentially include dot `.` character).
97  *
98  * A NULL @p aServiceType indicates that conflict is for a host entry. In this case @p Name specifies the host name. It
99  * does not include the domain name.
100  *
101  * @param[in] aInstance      The OpenThread instance.
102  * @param[in] aName          The host name or the service instance label.
103  * @param[in] aServiceType   The service type (e.g., `_tst._udp`).
104  *
105  */
106 typedef void (*otMdnsConflictCallback)(otInstance *aInstance, const char *aName, const char *aServiceType);
107 
108 /**
109  * Represents an mDNS host.
110  *
111  * This type is used to register or unregister a host (`otMdnsRegisterHost()` and `otMdnsUnregisterHost()`).
112  *
113  * See the description of each function for more details on how different fields are used in each case.
114  *
115  */
116 typedef otPlatDnssdHost otMdnsHost;
117 
118 /**
119  * Represents an mDNS service.
120  *
121  * This type is used to register or unregister a service (`otMdnsRegisterService()` and `otMdnsUnregisterService()`).
122  *
123  * See the description of each function for more details on how different fields are used in each case.
124  *
125  */
126 typedef otPlatDnssdService otMdnsService;
127 
128 /**
129  * Represents an mDNS key record.
130  *
131  * See `otMdnsRegisterKey()`, `otMdnsUnregisterKey()` for more details about fields in each case.
132  *
133  */
134 typedef otPlatDnssdKey otMdnsKey;
135 
136 /**
137  * Represents an mDNS entry iterator.
138  *
139  */
140 typedef struct otMdnsIterator otMdnsIterator;
141 
142 /**
143  * Represents a host/service/key entry state.
144  *
145  */
146 typedef enum otMdnsEntryState
147 {
148     OT_MDNS_ENTRY_STATE_PROBING,    ///< Probing to claim the name.
149     OT_MDNS_ENTRY_STATE_REGISTERED, ///< Entry is successfully registered.
150     OT_MDNS_ENTRY_STATE_CONFLICT,   ///< Name conflict was detected.
151     OT_MDNS_ENTRY_STATE_REMOVING,   ///< Entry is being removed (sending "goodbye" announcements).
152 } otMdnsEntryState;
153 
154 /**
155  * Enables or disables the mDNS module.
156  *
157  * The mDNS module should be enabled before registration any host, service, or key entries. Disabling mDNS will
158  * immediately stop all operations and any communication (multicast or unicast tx) and remove any previously registered
159  * entries without sending any "goodbye" announcements or invoking their callback. Once disabled, all currently active
160  * browsers and resolvers are stopped.
161  *
162  * @param[in] aInstance      The OpenThread instance.
163  * @param[in] aEnable        Boolean to indicate whether to enable (on `TRUE`) or disable (on `FALSE`).
164  * @param[in] aInfraIfIndex  The network interface index for mDNS operation. Value is ignored when disabling
165  *
166  * @retval OT_ERROR_NONE     Enabled or disabled the mDNS module successfully.
167  * @retval OT_ERROR_ALREADY  mDNS is already enabled on an enable request or is already disabled on a disable request.
168  *
169  */
170 otError otMdnsSetEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex);
171 
172 /**
173  * Indicates whether the mDNS module is enabled.
174  *
175  * @param[in] aInstance     The OpenThread instance.
176  *
177  * @retval TRUE    The mDNS module is enabled
178  * @retval FALSE   The mDNS module is disabled.
179  *
180  */
181 bool otMdnsIsEnabled(otInstance *aInstance);
182 
183 /**
184  * Sets whether the mDNS module is allowed to send questions requesting unicast responses referred to as "QU" questions.
185  *
186  * The "QU" questions request unicast responses, in contrast to "QM" questions which request multicast responses.
187  *
188  * When allowed, the first probe will be sent as a "QU" question. This API can be used to address platform limitation
189  * where platform socket cannot accept unicast response received on mDNS port (due to it being already bound).
190  *
191  * @param[in] aInstance     The OpenThread instance.
192  * @param[in] aAllow        Indicates whether or not to allow "QU" questions.
193  *
194  */
195 void otMdnsSetQuestionUnicastAllowed(otInstance *aInstance, bool aAllow);
196 
197 /**
198  * Indicates whether mDNS module is allowed to send "QU" questions requesting unicast response.
199  *
200  * @retval TRUE  The mDNS module is allowed to send "QU" questions.
201  * @retval FALSE The mDNS module is not allowed to send "QU" questions.
202  *
203  */
204 bool otMdnsIsQuestionUnicastAllowed(otInstance *aInstance);
205 
206 /**
207  * Sets the post-registration conflict callback.
208  *
209  * If a conflict is detected while registering an entry, it is reported through the provided `otMdnsRegisterCallback`.
210  * The `otMdnsConflictCallback` is used only when a name conflict is detected after an entry has been successfully
211  * registered.
212  *
213  * @p aCallback can be set to `NULL` if not needed. Subsequent calls will replace any previously set callback.
214  *
215  * @param[in] aInstance     The OpenThread instance.
216  * @param[in] aCallback     The conflict callback.
217  *
218  */
219 void otMdnsSetConflictCallback(otInstance *aInstance, otMdnsConflictCallback aCallback);
220 
221 /**
222  * Registers or updates a host on mDNS.
223  *
224  * The fields in @p aHost follow these rules:
225  *
226  * - The `mHostName` field specifies the host name to register (e.g., "myhost"). MUST NOT contain the domain name.
227  * - The `mAddresses` is array of IPv6 addresses to register with the host. `mAddressesLength` provides the number of
228  *   entries in `mAddresses` array.
229  * - The `mAddresses` array can be empty with zero `mAddressesLength`. In this case, mDNS will treat it as if host is
230  *   unregistered and stops advertising any addresses for this the host name.
231  * - The `mTtl` specifies the TTL if non-zero. If zero, the mDNS core will choose the default TTL of 120 seconds.
232  * - Other fields in @p aHost structure are ignored in an `otMdnsRegisterHost()` call.
233  *
234  * This function can be called again for the same `mHostName` to update a previously registered host entry, for example,
235  * to change the list of addresses of the host. In this case, the mDNS module will send "goodbye" announcements for any
236  * previously registered and now removed addresses and announce any newly added addresses.
237  *
238  * The outcome of the registration request is reported back by invoking the provided @p aCallback with @p aRequestId
239  * as its input and one of the following `aError` inputs:
240  *
241  * - `OT_ERROR_NONE` indicates registration was successful.
242  * - `OT_ERROR_DULICATED` indicates a name conflict while probing, i.e., name is claimed by another mDNS responder.
243  *
244  * For caller convenience, the OpenThread mDNS module guarantees that the callback will be invoked after this function
245  * returns, even in cases of immediate registration success. The @p aCallback can be `NULL` if caller does not want to
246  * be notified of the outcome.
247  *
248  * @param[in] aInstance     The OpenThread instance.
249  * @param[in] aHost         Information about the host to register.
250  * @param[in] aRequestId    The ID associated with this request.
251  * @param[in] aCallback     The callback function pointer to report the outcome (can be NULL if not needed).
252  *
253  * @retval OT_ERROR_NONE            Successfully started registration. @p aCallback will report the outcome.
254  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
255  *
256  */
257 otError otMdnsRegisterHost(otInstance            *aInstance,
258                            const otMdnsHost      *aHost,
259                            otMdnsRequestId        aRequestId,
260                            otMdnsRegisterCallback aCallback);
261 
262 /**
263  * Unregisters a host on mDNS.
264  *
265  * The fields in @p aHost follow these rules:
266  *
267  * - The `mHostName` field specifies the host name to unregister (e.g., "myhost"). MUST NOT contain the domain name.
268  * - Other fields in @p aHost structure are ignored in an `otMdnsUnregisterHost()` call.
269  *
270  * If there is no previously registered host with the same name, no action is performed.
271  *
272  * If there is a previously registered host with the same name, the mDNS module will send "goodbye" announcement for
273  * all previously advertised address records.
274  *
275  * @param[in] aInstance     The OpenThread instance.
276  * @param[in] aHost         Information about the host to unregister.
277  *
278  * @retval OT_ERROR_NONE            Successfully unregistered host.
279  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
280  *
281  */
282 otError otMdnsUnregisterHost(otInstance *aInstance, const otMdnsHost *aHost);
283 
284 /**
285  * Registers or updates a service on mDNS.
286  *
287  * The fields in @p aService follow these rules:
288  *
289  * - The `mServiceInstance` specifies the service instance label. It is treated as a single DNS name label. It may
290  *   contain dot `.` character which is allowed in a service instance label.
291  * - The `mServiceType` specifies the service type (e.g., "_tst._udp"). It is treated as multiple dot `.` separated
292  *   labels. It MUST NOT contain the domain name.
293  * - The `mHostName` field specifies the host name of the service. MUST NOT contain the domain name.
294  * - The `mSubTypeLabels` is an array of strings representing sub-types associated with the service. Each array entry
295  *   is a sub-type label. The `mSubTypeLabels can be NULL if there is no sub-type. Otherwise, the array length is
296  *   specified by `mSubTypeLabelsLength`.
297  * - The `mTxtData` and `mTxtDataLength` specify the encoded TXT data. The `mTxtData` can be NULL or `mTxtDataLength`
298  *   can be zero to specify an empty TXT data. In this case mDNS module will use a single zero byte `[ 0 ]` as the
299  *   TXT data.
300  * - The `mPort`, `mWeight`, and `mPriority` specify the service's parameters as specified in DNS SRV record.
301  * - The `mTtl` specifies the TTL if non-zero. If zero, the mDNS module will use the default TTL of 120 seconds.
302  * - Other fields in @p aService structure are ignored in an `otMdnsRegisterService()` call.
303  *
304  * This function can be called again for the same `mServiceInstance` and `mServiceType` to update a previously
305  * registered service entry, for example, to change the sub-types list, or update any parameter such as port, weight,
306  * priority, TTL, or host name. The mDNS module will send announcements for any changed info, e.g., will send "goodbye"
307  * announcements for any removed sub-types and announce any newly added sub-types.
308  *
309  * Regarding the invocation of the @p aCallback, this function behaves in the same way as described in
310  * `otMdnsRegisterHost()`.
311  *
312  * @param[in] aInstance     The OpenThread instance.
313  * @param[in] aService      Information about the service to register.
314  * @param[in] aRequestId    The ID associated with this request.
315  * @param[in] aCallback     The callback function pointer to report the outcome (can be NULL if not needed).
316  *
317  * @retval OT_ERROR_NONE            Successfully started registration. @p aCallback will report the outcome.
318  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
319  *
320  */
321 otError otMdnsRegisterService(otInstance            *aInstance,
322                               const otMdnsService   *aService,
323                               otMdnsRequestId        aRequestId,
324                               otMdnsRegisterCallback aCallback);
325 
326 /**
327  * Unregisters a service on mDNS module.
328  *
329  * The fields in @p aService follow these rules:
330 
331  * - The `mServiceInstance` specifies the service instance label. It is treated as a single DNS name label. It may
332  *   contain dot `.` character which is allowed in a service instance label.
333  * - The `mServiceType` specifies the service type (e.g., "_tst._udp"). It is treated as multiple dot `.` separated
334  *   labels. It MUST NOT contain the domain name.
335  * - Other fields in @p aService structure are ignored in an `otMdnsUnregisterService()` call.
336  *
337  * If there is no previously registered service with the same name, no action is performed.
338  *
339  * If there is a previously registered service with the same name, the mDNS module will send "goodbye" announcements
340  * for all related records.
341  *
342  * @param[in] aInstance     The OpenThread instance.
343  * @param[in] aService      Information about the service to unregister.
344  *
345  * @retval OT_ERROR_NONE            Successfully unregistered service.
346  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
347  *
348  */
349 otError otMdnsUnregisterService(otInstance *aInstance, const otMdnsService *aService);
350 
351 /**
352  * Registers or updates a key record on mDNS module.
353  *
354  * The fields in @p aKey follow these rules:
355  *
356  * - If the key is associated with a host entry, the `mName` field specifies the host name and the `mServiceType` MUST
357  *   be NULL.
358  * - If the key is associated with a service entry, the `mName` filed specifies the service instance label (always
359  *   treated as a single label) and the `mServiceType` filed specifies the service type (e.g., "_tst._udp"). In this
360  *   case the DNS name for key record is `<mName>.<mServiceTye>`.
361  * - The `mKeyData` field contains the key record's data with `mKeyDataLength` as its length in byes.
362  * - The `mTtl` specifies the TTL if non-zero. If zero, the mDNS module will use the default TTL of 120 seconds.
363  * - Other fields in @p aKey structure are ignored in an `otMdnsRegisterKey()` call.
364  *
365  * This function can be called again for the same name to updated a previously registered key entry, for example, to
366  * change the key data or TTL.
367  *
368  * Regarding the invocation of the @p aCallback, this function behaves in the same way as described in
369  * `otMdnsRegisterHost()`.
370  *
371  * @param[in] aInstance     The OpenThread instance.
372  * @param[in] aKey          Information about the key record to register.
373  * @param[in] aRequestId    The ID associated with this request.
374  * @param[in] aCallback     The callback function pointer to report the outcome (can be NULL if not needed).
375  *
376  * @retval OT_ERROR_NONE            Successfully started registration. @p aCallback will report the outcome.
377  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
378  *
379  */
380 otError otMdnsRegisterKey(otInstance            *aInstance,
381                           const otMdnsKey       *aKey,
382                           otMdnsRequestId        aRequestId,
383                           otMdnsRegisterCallback aCallback);
384 
385 /**
386  * Unregisters a key record on mDNS.
387  *
388  * The fields in @p aKey follow these rules:
389  *
390  * - If the key is associated with a host entry, the `mName` field specifies the host name and the `mServiceType` MUST
391  *   be NULL.
392  * - If the key is associated with a service entry, the `mName` filed specifies the service instance label (always
393  *   treated as a single label) and the `mServiceType` filed specifies the service type (e.g., "_tst._udp"). In this
394  *   case the DNS name for key record is `<mName>.<mServiceTye>`.
395  * - Other fields in @p aKey structure are ignored in an `otMdnsUnregisterKey()` call.
396  *
397  * If there is no previously registered key with the same name, no action is performed.
398  *
399  * If there is a previously registered key with the same name, the mDNS module will send "goodbye" announcements for
400  * the key record.
401  *
402  * @param[in] aInstance     The OpenThread instance.
403  * @param[in] aKey          Information about the key to unregister.
404  *
405  * @retval OT_ERROR_NONE            Successfully unregistered key
406  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
407  *
408  */
409 otError otMdnsUnregisterKey(otInstance *aInstance, const otMdnsKey *aKey);
410 
411 /**
412  * Allocates a new iterator.
413  *
414  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
415  *
416  * An allocated iterator must be freed by the caller using `otMdnsFreeIterator()`.
417  *
418  * @param[in] aInstance    The OpenThread instance.
419  *
420  * @returns A pointer to the allocated iterator, or `NULL` if it fails to allocate.
421  *
422  */
423 otMdnsIterator *otMdnsAllocateIterator(otInstance *aInstance);
424 
425 /**
426  * Frees a previously allocated iterator.
427  *
428  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
429  *
430  * @param[in] aInstance    The OpenThread instance.
431  * @param[in] aIterator    The iterator to free.
432  *
433  */
434 void otMdnsFreeIterator(otInstance *aInstance, otMdnsIterator *aIterator);
435 
436 /**
437  * Iterates over registered host entries.
438  *
439  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
440  *
441  * On success, @p aHost is populated with information about the next host. Pointers within the `otMdnsHost` structure
442  * (like `mName`) remain valid until the next call to any OpenThread stack's public or platform API/callback.
443  *
444  * @param[in]  aInstance   The OpenThread instance.
445  * @param[in]  aIterator   Pointer to the iterator.
446  * @param[out] aHost       Pointer to an `otMdnsHost` to return the information about the next host entry.
447  * @param[out] aState      Pointer to an `otMdnsEntryState` to return the entry state.
448  *
449  * @retval OT_ERROR_NONE         @p aHost, @p aState, & @p aIterator are updated successfully.
450  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
451  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
452  *
453  */
454 otError otMdnsGetNextHost(otInstance       *aInstance,
455                           otMdnsIterator   *aIterator,
456                           otMdnsHost       *aHost,
457                           otMdnsEntryState *aState);
458 
459 /**
460  * Iterates over registered service entries.
461  *
462  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
463  *
464  * On success, @p aService is populated with information about the next service . Pointers within the `otMdnsService`
465  * structure (like `mServiceType`, `mSubTypeLabels`) remain valid until the next call to any OpenThread stack's public
466  * or platform API/callback.
467  *
468  * @param[in]  aInstance    The OpenThread instance.
469  * @param[in]  aIterator    Pointer to the iterator to use.
470  * @param[out] aService     Pointer to an `otMdnsService` to return the information about the next service entry.
471  * @param[out] aState       Pointer to an `otMdnsEntryState` to return the entry state.
472  *
473  * @retval OT_ERROR_NONE         @p aService, @p aState, & @p aIterator are updated successfully.
474  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
475  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
476  *
477  */
478 otError otMdnsGetNextService(otInstance       *aInstance,
479                              otMdnsIterator   *aIterator,
480                              otMdnsService    *aService,
481                              otMdnsEntryState *aState);
482 
483 /**
484  * Iterates over registered key entries.
485  *
486  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
487  *
488  * On success, @p aKey is populated with information about the next key.  Pointers within the `otMdnsKey` structure
489  * (like `mName`) remain valid until the next call to any OpenThread stack's public or platform API/callback.
490  *
491  * @param[in]  aInstance    The OpenThread instance.
492  * @param[in]  aIterator    Pointer to the iterator to use.
493  * @param[out] aKey         Pointer to an `otMdnsKey` to return the information about the next key entry.
494  * @param[out] aState       Pointer to an `otMdnsEntryState` to return the entry state.
495  *
496  * @retval OT_ERROR_NONE         @p aKey, @p aState, & @p aIterator are updated successfully.
497  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
498  * @retval OT_ERROR_INVALID_ARG  Iterator is not valid.
499  *
500  */
501 otError otMdnsGetNextKey(otInstance *aInstance, otMdnsIterator *aIterator, otMdnsKey *aKey, otMdnsEntryState *aState);
502 
503 typedef struct otMdnsBrowseResult  otMdnsBrowseResult;
504 typedef struct otMdnsSrvResult     otMdnsSrvResult;
505 typedef struct otMdnsTxtResult     otMdnsTxtResult;
506 typedef struct otMdnsAddressResult otMdnsAddressResult;
507 
508 /**
509  * Represents the callback function used to report a browse result.
510  *
511  * @param[in] aInstance    The OpenThread instance.
512  * @param[in] aResult      The browse result.
513  *
514  */
515 typedef void (*otMdnsBrowseCallback)(otInstance *aInstance, const otMdnsBrowseResult *aResult);
516 
517 /**
518  * Represents the callback function used to report an SRV resolve result.
519  *
520  * @param[in] aInstance    The OpenThread instance.
521  * @param[in] aResult      The SRV resolve result.
522  *
523  */
524 typedef void (*otMdnsSrvCallback)(otInstance *aInstance, const otMdnsSrvResult *aResult);
525 
526 /**
527  * Represents the callback function used to report a TXT resolve result.
528  *
529  * @param[in] aInstance    The OpenThread instance.
530  * @param[in] aResult      The TXT resolve result.
531  *
532  */
533 typedef void (*otMdnsTxtCallback)(otInstance *aInstance, const otMdnsTxtResult *aResult);
534 
535 /**
536  * Represents the callback function use to report a IPv6/IPv4 address resolve result.
537  *
538  * @param[in] aInstance    The OpenThread instance.
539  * @param[in] aResult      The address resolve result.
540  *
541  */
542 typedef void (*otMdnsAddressCallback)(otInstance *aInstance, const otMdnsAddressResult *aResult);
543 
544 /**
545  * Represents a service browser.
546  *
547  */
548 typedef struct otMdnsBrowser
549 {
550     const char          *mServiceType;  ///< The service type (e.g., "_mt._udp"). MUST NOT include domain name.
551     const char          *mSubTypeLabel; ///< The sub-type label if browsing for sub-type, NULL otherwise.
552     uint32_t             mInfraIfIndex; ///< The infrastructure network interface index.
553     otMdnsBrowseCallback mCallback;     ///< The callback to report result.
554 } otMdnsBrowser;
555 
556 /**
557  * Represents a browse result.
558  *
559  */
560 struct otMdnsBrowseResult
561 {
562     const char *mServiceType;     ///< The service type (e.g., "_mt._udp").
563     const char *mSubTypeLabel;    ///< The sub-type label if browsing for sub-type, NULL otherwise.
564     const char *mServiceInstance; ///< Service instance label.
565     uint32_t    mTtl;             ///< TTL in seconds. Zero TTL indicates that service is removed.
566     uint32_t    mInfraIfIndex;    ///< The infrastructure network interface index.
567 };
568 
569 /**
570  * Represents an SRV service resolver.
571  *
572  */
573 typedef struct otMdnsSrvResolver
574 {
575     const char       *mServiceInstance; ///< The service instance label.
576     const char       *mServiceType;     ///< The service type.
577     uint32_t          mInfraIfIndex;    ///< The infrastructure network interface index.
578     otMdnsSrvCallback mCallback;        ///< The callback to report result.
579 } otMdnsSrvResolver;
580 
581 /**
582  * Represents an SRV resolver result.
583  *
584  */
585 struct otMdnsSrvResult
586 {
587     const char *mServiceInstance; ///< The service instance name label.
588     const char *mServiceType;     ///< The service type.
589     const char *mHostName;        ///< The host name (e.g., "myhost"). Can be NULL when `mTtl` is zero.
590     uint16_t    mPort;            ///< The service port number.
591     uint16_t    mPriority;        ///< The service priority.
592     uint16_t    mWeight;          ///< The service weight.
593     uint32_t    mTtl;             ///< The service TTL in seconds. Zero TTL indicates SRV record is removed.
594     uint32_t    mInfraIfIndex;    ///< The infrastructure network interface index.
595 };
596 
597 /**
598  * Represents a TXT service resolver.
599  *
600  */
601 typedef struct otMdnsTxtResolver
602 {
603     const char       *mServiceInstance; ///< Service instance label.
604     const char       *mServiceType;     ///< Service type.
605     uint32_t          mInfraIfIndex;    ///< The infrastructure network interface index.
606     otMdnsTxtCallback mCallback;
607 } otMdnsTxtResolver;
608 
609 /**
610  * Represents a TXT resolver result.
611  *
612  */
613 struct otMdnsTxtResult
614 {
615     const char    *mServiceInstance; ///< The service instance name label.
616     const char    *mServiceType;     ///< The service type.
617     const uint8_t *mTxtData;         ///< Encoded TXT data bytes. Can be NULL when `mTtl` is zero.
618     uint16_t       mTxtDataLength;   ///< Length of TXT data.
619     uint32_t       mTtl;             ///< The TXT data TTL in seconds. Zero TTL indicates record is removed.
620     uint32_t       mInfraIfIndex;    ///< The infrastructure network interface index.
621 };
622 
623 /**
624  * Represents an address resolver.
625  *
626  */
627 typedef struct otMdnsAddressResolver
628 {
629     const char           *mHostName;     ///< The host name (e.g., "myhost"). MUST NOT contain domain name.
630     uint32_t              mInfraIfIndex; ///< The infrastructure network interface index.
631     otMdnsAddressCallback mCallback;     ///< The callback to report result.
632 } otMdnsAddressResolver;
633 
634 /**
635  * Represents a discovered host address and its TTL.
636  *
637  */
638 typedef struct otMdnsAddressAndTtl
639 {
640     otIp6Address mAddress; ///< The IPv6 address. For IPv4 address the IPv4-mapped IPv6 address format is used.
641     uint32_t     mTtl;     ///< The TTL in seconds.
642 } otMdnsAddressAndTtl;
643 
644 /**
645  * Represents address resolver result.
646  *
647  */
648 struct otMdnsAddressResult
649 {
650     const char                *mHostName;        ///< The host name.
651     const otMdnsAddressAndTtl *mAddresses;       ///< Array of host addresses and their TTL. Can be NULL if empty.
652     uint16_t                   mAddressesLength; ///< Number of entries in `mAddresses` array.
653     uint32_t                   mInfraIfIndex;    ///< The infrastructure network interface index.
654 };
655 
656 /**
657  * Starts a service browser.
658  *
659  * Initiates a continuous search for the specified `mServiceType` in @p aBrowser. For sub-type services, use
660  * `mSubTypeLabel` to define the sub-type, for base services, set `mSubTypeLabel` to NULL.
661  *
662  * Discovered services are reported through the `mCallback` function in @p aBrowser. Services that have been removed
663  * are reported with a TTL value of zero. The callback may be invoked immediately with cached information (if available)
664  * and potentially before this function returns. When cached results are used, the reported TTL value will reflect
665  * the original TTL from the last received response.
666  *
667  * Multiple browsers can be started for the same service, provided they use different callback functions.
668  *
669  * @param[in] aInstance   The OpenThread instance.
670  * @param[in] aBrowser    The browser to be started.
671  *
672  * @retval OT_ERROR_NONE           Browser started successfully.
673  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
674  * @retval OT_ERROR_ALREADY        An identical browser (same service and callback) is already active.
675  *
676  */
677 otError otMdnsStartBrowser(otInstance *aInstance, const otMdnsBrowser *aBrowser);
678 
679 /**
680  * Stops a service browser.
681  *
682  * No action is performed if no matching browser with the same service and callback is currently active.
683  *
684  * @param[in] aInstance   The OpenThread instance.
685  * @param[in] aBrowser    The browser to stop.
686  *
687  * @retval OT_ERROR_NONE           Browser stopped successfully.
688  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
689  *
690  */
691 otError otMdnsStopBrowser(otInstance *aInstance, const otMdnsBrowser *aBroswer);
692 
693 /**
694  * Starts an SRV record resolver.
695  *
696  * Initiates a continuous SRV record resolver for the specified service in @p aResolver.
697  *
698  * Discovered information is reported through the `mCallback` function in @p aResolver. When the service is removed
699  * it is reported with a TTL value of zero. In this case, `mHostName` may be NULL and other result fields (such as
700  * `mPort`) should be ignored.
701  *
702  * The callback may be invoked immediately with cached information (if available) and potentially before this function
703  * returns. When cached result is used, the reported TTL value will reflect the original TTL from the last received
704  * response.
705  *
706  * Multiple resolvers can be started for the same service, provided they use different callback functions.
707  *
708  * @param[in] aInstance    The OpenThread instance.
709  * @param[in] aResolver    The resolver to be started.
710  *
711  * @retval OT_ERROR_NONE           Resolver started successfully.
712  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
713  * @retval OT_ERROR_ALREADY        An identical resolver (same service and callback) is already active.
714  *
715  */
716 otError otMdnsStartSrvResolver(otInstance *aInstance, const otMdnsSrvResolver *aResolver);
717 
718 /**
719  * Stops an SRV record resolver.
720  *
721  * No action is performed if no matching resolver with the same service and callback is currently active.
722  *
723  * @param[in] aInstance    The OpenThread instance.
724  * @param[in] aResolver    The resolver to stop.
725  *
726  * @retval OT_ERROR_NONE           Resolver stopped successfully.
727  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
728  *
729  */
730 otError otMdnsStopSrvResolver(otInstance *aInstance, const otMdnsSrvResolver *aResolver);
731 
732 /**
733  * Starts a TXT record resolver.
734  *
735  * Initiates a continuous TXT record resolver for the specified service in @p aResolver.
736  *
737  * Discovered information is reported through the `mCallback` function in @p aResolver. When the TXT record is removed
738  * it is reported with a TTL value of zero. In this case, `mTxtData` may be NULL, and other result fields (such as
739  * `mTxtDataLength`) should be ignored.
740  *
741  * The callback may be invoked immediately with cached information (if available) and potentially before this function
742  * returns. When cached result is used, the reported TTL value will reflect the original TTL from the last received
743  * response.
744  *
745  * Multiple resolvers can be started for the same service, provided they use different callback functions.
746  *
747  * @param[in] aInstance    The OpenThread instance.
748  * @param[in] aResolver    The resolver to be started.
749  *
750  * @retval OT_ERROR_NONE           Resolver started successfully.
751  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
752  * @retval OT_ERROR_ALREADY        An identical resolver (same service and callback) is already active.
753  *
754  */
755 otError otMdnsStartTxtResolver(otInstance *aInstance, const otMdnsTxtResolver *aResolver);
756 
757 /**
758  * Stops a TXT record resolver.
759  *
760  * No action is performed if no matching resolver with the same service and callback is currently active.
761  *
762  * @param[in] aInstance    The OpenThread instance.
763  * @param[in] aResolver    The resolver to stop.
764  *
765  * @retval OT_ERROR_NONE           Resolver stopped successfully.
766  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
767  *
768  */
769 otError otMdnsStopTxtResolver(otInstance *aInstance, const otMdnsTxtResolver *aResolver);
770 
771 /**
772  * Starts an IPv6 address resolver.
773  *
774  * Initiates a continuous IPv6 address resolver for the specified host name in @p aResolver.
775  *
776  * Discovered addresses are reported through the `mCallback` function in @p aResolver. The callback is invoked
777  * whenever addresses are added or removed, providing an updated list. If all addresses are removed, the callback is
778  * invoked with an empty list (`mAddresses` will be NULL, and `mAddressesLength` will be zero).
779  *
780  * The callback may be invoked immediately with cached information (if available) and potentially before this function
781  * returns. When cached result is used, the reported TTL values will reflect the original TTL from the last received
782  * response.
783  *
784  * Multiple resolvers can be started for the same host name, provided they use different callback functions.
785  *
786  * @param[in] aInstance    The OpenThread instance.
787  * @param[in] aResolver    The resolver to be started.
788  *
789  * @retval OT_ERROR_NONE           Resolver started successfully.
790  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
791  * @retval OT_ERROR_ALREADY        An identical resolver (same host and callback) is already active.
792  *
793  */
794 otError otMdnsStartIp6AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
795 
796 /**
797  * Stops an IPv6 address resolver.
798  *
799  * No action is performed if no matching resolver with the same host name and callback is currently active.
800  *
801  * @param[in] aInstance    The OpenThread instance.
802  * @param[in] aResolver    The resolver to stop.
803  *
804  * @retval OT_ERROR_NONE           Resolver stopped successfully.
805  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
806  *
807  */
808 otError otMdnsStopIp6AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
809 
810 /**
811  * Starts an IPv4 address resolver.
812  *
813  * Initiates a continuous IPv4 address resolver for the specified host name in @p aResolver.
814  *
815  * Discovered addresses are reported through the `mCallback` function in @p aResolver. The IPv4 addresses are
816  * represented using the IPv4-mapped IPv6 address format in `mAddresses` array.  The callback is invoked  whenever
817  * addresses are added or removed, providing an updated list. If all addresses are removed, the callback is invoked
818  * with an empty list (`mAddresses` will be NULL, and `mAddressesLength` will be zero).
819  *
820  * The callback may be invoked immediately with cached information (if available) and potentially before this function
821  * returns. When cached result is used, the reported TTL values will reflect the original TTL from the last received
822  * response.
823  *
824  * Multiple resolvers can be started for the same host name, provided they use different callback functions.
825  *
826  * @param[in] aInstance    The OpenThread instance.
827  * @param[in] aResolver    The resolver to be started.
828  *
829  * @retval OT_ERROR_NONE           Resolver started successfully.
830  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
831  * @retval OT_ERROR_ALREADY        An identical resolver (same host and callback) is already active.
832  *
833  */
834 otError otMdnsStartIp4AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
835 
836 /**
837  * Stops an IPv4 address resolver.
838  *
839  * No action is performed if no matching resolver with the same host name and callback is currently active.
840  *
841  * @param[in] aInstance    The OpenThread instance.
842  * @param[in] aResolver    The resolver to stop.
843  *
844  * @retval OT_ERROR_NONE           Resolver stopped successfully.
845  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
846  *
847  */
848 otError otMdnsStopIp4AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
849 
850 /**
851  * Represents additional information about a browser/resolver and its cached results.
852  *
853  */
854 typedef struct otMdnsCacheInfo
855 {
856     bool mIsActive;         ///< Whether this is an active browser/resolver vs an opportunistic cached one.
857     bool mHasCachedResults; ///< Whether there is any cached results.
858 } otMdnsCacheInfo;
859 
860 /**
861  * Iterates over browsers.
862  *
863  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
864  *
865  * On success, @p aBrowser is populated with information about the next browser. The `mCallback` field is always
866  * set to `NULL` as there may be multiple active browsers with different callbacks. Other pointers within the
867  * `otMdnsBrowser` structure remain valid until the next call to any OpenThread stack's public or platform API/callback.
868  *
869  * @param[in]  aInstance   The OpenThread instance.
870  * @param[in]  aIterator   Pointer to the iterator.
871  * @param[out] aBrowser    Pointer to an `otMdnsBrowser` to return the information about the next browser.
872  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
873  *
874  * @retval OT_ERROR_NONE         @p aBrowser, @p aInfo, & @p aIterator are updated successfully.
875  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
876  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
877  *
878  */
879 otError otMdnsGetNextBrowser(otInstance      *aInstance,
880                              otMdnsIterator  *aIterator,
881                              otMdnsBrowser   *aBrowser,
882                              otMdnsCacheInfo *aInfo);
883 
884 /**
885  * Iterates over SRV resolvers.
886  *
887  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
888  *
889  * On success, @p aResolver is populated with information about the next resolver. The `mCallback` field is always
890  * set to `NULL` as there may be multiple active resolvers with different callbacks. Other pointers within the
891  * `otMdnsSrvResolver` structure remain valid until the next call to any OpenThread stack's public or platform
892  * API/callback.
893  *
894  * @param[in]  aInstance   The OpenThread instance.
895  * @param[in]  aIterator   Pointer to the iterator.
896  * @param[out] aResolver   Pointer to an `otMdnsSrvResolver` to return the information about the next resolver.
897  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
898  *
899  * @retval OT_ERROR_NONE         @p aResolver, @p aInfo, & @p aIterator are updated successfully.
900  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
901  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
902  *
903  */
904 otError otMdnsGetNextSrvResolver(otInstance        *aInstance,
905                                  otMdnsIterator    *aIterator,
906                                  otMdnsSrvResolver *aResolver,
907                                  otMdnsCacheInfo   *aInfo);
908 
909 /**
910  * Iterates over TXT resolvers.
911  *
912  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
913  *
914  * On success, @p aResolver is populated with information about the next resolver. The `mCallback` field is always
915  * set to `NULL` as there may be multiple active resolvers with different callbacks. Other pointers within the
916  * `otMdnsTxtResolver` structure remain valid until the next call to any OpenThread stack's public or platform
917  * API/callback.
918  *
919  * @param[in]  aInstance   The OpenThread instance.
920  * @param[in]  aIterator   Pointer to the iterator.
921  * @param[out] aResolver   Pointer to an `otMdnsTxtResolver` to return the information about the next resolver.
922  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
923  *
924  * @retval OT_ERROR_NONE         @p aResolver, @p aInfo, & @p aIterator are updated successfully.
925  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
926  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
927  *
928  */
929 otError otMdnsGetNextTxtResolver(otInstance        *aInstance,
930                                  otMdnsIterator    *aIterator,
931                                  otMdnsTxtResolver *aResolver,
932                                  otMdnsCacheInfo   *aInfo);
933 
934 /**
935  * Iterates over IPv6 address resolvers.
936  *
937  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
938  *
939  * On success, @p aResolver is populated with information about the next resolver. The `mCallback` field is always
940  * set to `NULL` as there may be multiple active resolvers with different callbacks. Other pointers within the
941  * `otMdnsAddressResolver` structure remain valid until the next call to any OpenThread stack's public or platform
942  * API/callback.
943  *
944  * @param[in]  aInstance   The OpenThread instance.
945  * @param[in]  aIterator   Pointer to the iterator.
946  * @param[out] aResolver   Pointer to an `otMdnsAddressResolver` to return the information about the next resolver.
947  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
948  *
949  * @retval OT_ERROR_NONE         @p aResolver, @p aInfo, & @p aIterator are updated successfully.
950  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
951  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
952  *
953  */
954 otError otMdnsGetNextIp6AddressResolver(otInstance            *aInstance,
955                                         otMdnsIterator        *aIterator,
956                                         otMdnsAddressResolver *aResolver,
957                                         otMdnsCacheInfo       *aInfo);
958 
959 /**
960  * Iterates over IPv4 address resolvers.
961  *
962  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
963  *
964  * On success, @p aResolver is populated with information about the next resolver. The `mCallback` field is always
965  * set to `NULL` as there may be multiple active resolvers with different callbacks. Other pointers within the
966  * `otMdnsAddressResolver` structure remain valid until the next call to any OpenThread stack's public or platform
967  * API/callback.
968  *
969  * @param[in]  aInstance   The OpenThread instance.
970  * @param[in]  aIterator   Pointer to the iterator.
971  * @param[out] aResolver   Pointer to an `otMdnsAddressResolver` to return the information about the next resolver.
972  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
973  *
974  * @retval OT_ERROR_NONE         @p aResolver, @p aInfo, & @p aIterator are updated successfully.
975  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
976  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
977  *
978  */
979 otError otMdnsGetNextIp4AddressResolver(otInstance            *aInstance,
980                                         otMdnsIterator        *aIterator,
981                                         otMdnsAddressResolver *aResolver,
982                                         otMdnsCacheInfo       *aInfo);
983 
984 /**
985  * @}
986  *
987  */
988 
989 #ifdef __cplusplus
990 } // extern "C"
991 #endif
992 
993 #endif // OPENTHREAD_MULTICAST_DNS_H_
994