1 /* 2 * Copyright (c) 2023, 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 platform abstraction for DNS-SD (e.g., mDNS) on the infrastructure network. 33 * 34 */ 35 36 #ifndef OPENTHREAD_PLATFORM_DNSSD_H_ 37 #define OPENTHREAD_PLATFORM_DNSSD_H_ 38 39 #include <stdint.h> 40 41 #include <openthread/dns.h> 42 #include <openthread/error.h> 43 #include <openthread/instance.h> 44 #include <openthread/ip6.h> 45 46 #ifdef __cplusplus 47 extern "C" { 48 #endif 49 50 /** 51 * @addtogroup plat-dns-sd 52 * 53 * @brief 54 * This module includes the platform abstraction for DNS-SD (e.g., mDNS) on the infrastructure network. 55 * 56 * @{ 57 * 58 * The DNS-SD platform APIs are used only when `OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE` is enabled. 59 * 60 */ 61 62 /** 63 * Represents the state of the DNS-SD platform. 64 * 65 */ 66 typedef enum otPlatDnssdState 67 { 68 OT_PLAT_DNSSD_STOPPED, ///< Stopped and unable to register any service or host. 69 OT_PLAT_DNSSD_READY, ///< Running and ready to register service or host. 70 } otPlatDnssdState; 71 72 /** 73 * Represents a request ID for registering/unregistering a service or host. 74 * 75 */ 76 typedef uint32_t otPlatDnssdRequestId; 77 78 /** 79 * Represents the callback function used when registering/unregistering a host or service. 80 * 81 * See `otPlatDnssdRegisterService()`, `otPlatDnssdUnregisterService()`, `otPlatDnssdRegisterHost()`, and 82 * `otPlatDnssdUnregisterHost()` for more details about when to invoke the callback and the `aError` values that can 83 * be returned in each case. 84 * 85 * @param[in] aInstance The OpenThread instance. 86 * @param[in] aRequestId The request ID. 87 * @param[in] aError Error indicating the outcome of request. 88 * 89 */ 90 typedef void (*otPlatDnssdRegisterCallback)(otInstance *aInstance, otPlatDnssdRequestId aRequestId, otError aError); 91 92 /** 93 * Represents a DNS-SD service. 94 * 95 * See `otPlatDnssdRegisterService()`, `otPlatDnssdUnregisterService()` for more details about fields in each case. 96 * 97 */ 98 typedef struct otPlatDnssdService 99 { 100 const char *mHostName; ///< The host name (does not include domain name). 101 const char *mServiceInstance; ///< The service instance name label (not the full name). 102 const char *mServiceType; ///< The service type (e.g., "_mt._udp", does not include domain name). 103 const char *const *mSubTypeLabels; ///< Array of sub-type labels (can be NULL if no label). 104 uint16_t mSubTypeLabelsLength; ///< Length of array of sub-type labels. 105 const uint8_t *mTxtData; ///< Encoded TXT data bytes. 106 uint16_t mTxtDataLength; ///< Length of TXT data. 107 uint16_t mPort; ///< The service port number. 108 uint16_t mPriority; ///< The service priority. 109 uint16_t mWeight; ///< The service weight. 110 uint32_t mTtl; ///< The service TTL in seconds. 111 uint32_t mInfraIfIndex; ///< The infrastructure network interface index. 112 } otPlatDnssdService; 113 114 /** 115 * Represents a DNS-SD host. 116 * 117 * See `otPlatDnssdRegisterHost()`, `otPlatDnssdUnregisterHost()` for more details about fields in each case. 118 * 119 */ 120 typedef struct otPlatDnssdHost 121 { 122 const char *mHostName; ///< The host name (does not include domain name). 123 const otIp6Address *mAddresses; ///< Array of IPv6 host addresses. 124 uint16_t mAddressesLength; ///< Number of entries in @p mAddresses array. 125 uint32_t mTtl; ///< The host TTL in seconds. 126 uint32_t mInfraIfIndex; ///< The infrastructure network interface index. 127 } otPlatDnssdHost; 128 129 /** 130 * Represents a DNS-SD key record. 131 * 132 * See `otPlatDnssdRegisterKey()`, `otPlatDnssdUnregisterKey()` for more details about fields in each case. 133 * 134 */ 135 typedef struct otPlatDnssdKey 136 { 137 const char *mName; ///< A host or a service instance name (does not include domain name). 138 const char *mServiceType; ///< The service type if key is for a service (does not include domain name). 139 const uint8_t *mKeyData; ///< Byte array containing the key record data. 140 uint16_t mKeyDataLength; ///< Length of @p mKeyData in bytes. 141 uint16_t mClass; ///< The resource record class. 142 uint32_t mTtl; ///< The TTL in seconds. 143 uint32_t mInfraIfIndex; ///< The infrastructure network interface index. 144 } otPlatDnssdKey; 145 146 /** 147 * Callback to notify state changes of the DNS-SD platform. 148 * 149 * The OpenThread stack will call `otPlatDnssdGetState()` (from this callback or later) to get the new state. The 150 * platform MUST therefore ensure that the returned state from `otPlatDnssdGetState()` is updated before calling this. 151 * 152 * @param[in] aInstance The OpenThread instance structure. 153 * 154 */ 155 extern void otPlatDnssdStateHandleStateChange(otInstance *aInstance); 156 157 /** 158 * Gets the current state of the DNS-SD module. 159 * 160 * The platform MUST notify the OpenThread stack whenever its state gets changed by invoking 161 * `otPlatDnssdStateHandleStateChange()`. 162 * 163 * @param[in] aInstance The OpenThread instance. 164 * 165 * @returns The current state of the DNS-SD module. 166 * 167 */ 168 otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance); 169 170 /** 171 * Registers or updates a service on the infrastructure network's DNS-SD module. 172 * 173 * The @p aService and all its contained information (strings and buffers) are only valid during this call. The 174 * platform MUST save a copy of the information if it wants to retain the information after returning from this 175 * function. 176 * 177 * The fields in @p aService follow these rules: 178 * 179 * - The `mServiceInstance` and `mServiceType` fields specify the service instance label and service type name, 180 * respectively. They are never NULL. 181 * - The `mHostName` field specifies the host name of the service if it is not NULL. Otherwise, if it is NULL, it 182 * indicates that this service is for the device itself and leaves the host name selection to DNS-SD platform. 183 * - The `mSubTypeLabels` is an array of strings representing sub-types associated with the service. It can be NULL 184 * if there are no sub-types. Otherwise, the array length is specified by `mSubTypeLabelsLength`. 185 * - The `mTxtData` and `mTxtDataLength` fields specify the encoded TXT data. 186 * - The `mPort`, `mWeight`, and `mPriority` fields specify the service's parameters (as specified in DNS SRV record). 187 * - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use. 188 * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this 189 * request. If zero, the platform implementation can decided the interface. 190 * 191 * When the `mHostName` field in @p aService is not NULL (indicating that this registration is on behalf of another 192 * host), the OpenThread stack will ensure that `otPlatDnssdRegisterHost()` is also called for the same host before any 193 * service registration requests for the same host. 194 * 195 * Once the registration request is finished, either successfully or failed, the platform reports the outcome by 196 * invoking the @p aCallback and passing the same @p aRequestId in the callback. The @p aCallback function pointer can 197 * be NULL, which indicates that the OpenThread stack does not need to be notified of the outcome of the request. 198 * If the outcome is determined, the platform implementation may invoke the @p aCallback before returning from this 199 * function. The OpenThread stack will ensure to handle such a situation. 200 * 201 * On success, the @p aCallback MUST be called (if non-NULL) with `OT_ERROR_NONE` as the `aError` input parameter. If 202 * the registration causes a name conflict on DNS-SD domain (the service instance name is already claimed by another 203 * host), the `OT_ERROR_DUPLICATED` error MUST be used. The platform implementation can use other `OT_ERROR` types for 204 * other types of errors. 205 * 206 * The platform implementation MUST not assume that the @p aRequestId used in subsequent requests will be different. 207 * OpenThread may reuse the same request ID again for a different request. 208 * 209 * The OpenThread stack will not register the same service (with no changes) that was registered successfully earlier. 210 * Therefore, the platform implementation does not need to check for duplicate/same service and can assume that calls 211 * to this function are either registering a new entry or changing some parameter in a previously registered item. As 212 * a result, these changes always need to be synced on the infrastructure DNS-SD module. 213 * 214 * The OpenThread stack does not require the platform implementation to always invoke the @p aCallback function. 215 * The OpenThread stack has its own mechanism to time out an aged request with no response. This relaxes the 216 * requirement for platform implementations. 217 * 218 * @param[in] aInstance The OpenThread instance. 219 * @param[in] aService Information about the service to register. 220 * @param[in] aRequestId The ID associated with this request. 221 * @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed). 222 * 223 */ 224 void otPlatDnssdRegisterService(otInstance *aInstance, 225 const otPlatDnssdService *aService, 226 otPlatDnssdRequestId aRequestId, 227 otPlatDnssdRegisterCallback aCallback); 228 229 /** 230 * Unregisters a service on the infrastructure network's DNS-SD module. 231 * 232 * The @p aService and all its contained information (strings and buffers) are only valid during this call. The 233 * platform MUST save a copy of the information if it wants to retain the information after returning from this 234 * function. 235 * 236 * The fields in @p aService follow these rules: 237 * 238 * - The `mServiceInstance` and `mServiceType` fields specify the service instance label and service type name, 239 * respectively. They are never NULL. 240 * - The `mHostName` field specifies the host name of the service if it is not NULL. Otherwise, if it is NULL, it 241 * indicates that this service is for the device itself and leaves the host name selection to DNS-SD platform. 242 * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this 243 * request. If zero, the platform implementation can decided the interface. 244 * - The rest of the fields in @p aService structure MUST be ignored in `otPlatDnssdUnregisterService()` call and may 245 * be set to zero by the OpenThread stack. 246 * 247 * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same 248 * rules as described in `otPlatDnssdRegisterService()`. 249 * 250 * The OpenThread stack may request the unregistration of a service that was not previously registered, and the 251 * platform implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to 252 * indicate that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. The 253 * OpenThread stack will handle either case correctly. 254 * 255 * @param[in] aInstance The OpenThread instance. 256 * @param[in] aService Information about the service to unregister. 257 * @param[in] aRequestId The ID associated with this request. 258 * @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed). 259 * 260 */ 261 void otPlatDnssdUnregisterService(otInstance *aInstance, 262 const otPlatDnssdService *aService, 263 otPlatDnssdRequestId aRequestId, 264 otPlatDnssdRegisterCallback aCallback); 265 266 /** 267 * Registers or updates a host on the infrastructure network's DNS-SD module. 268 * 269 * The @p aHost and all its contained information (strings and arrays) are only valid during this call. The 270 * platform MUST save a copy of the information if it wants to retain the information after returning from this 271 * function. 272 * 273 * The fields in @p aHost follow these rules: 274 * 275 * - The `mHostName` field specifies the host name to register. It is never NULL. 276 * - The `mAddresses` field is an array of IPv6 addresses to register with the host. `mAddressesLength` field provides 277 * the number of entries in `mAddresses` array. The platform implementation MUST not filter or remove any of 278 * addresses in the list. 279 * The OpenThread stack will already ensure that the given addresses are externally reachable. For example, when 280 * registering host from an SRP registration, link-local or mesh-local addresses associated with the host which are 281 * intended for use within Thread mesh are not included in `mAddresses` array passed to this API. The `mAddresses` 282 * array can be empty with zero `mAddressesLength`. In such a case, the platform MUST stop advertising any addresses 283 * for this host name on the infrastructure DNS-SD. 284 * - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use. 285 * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this 286 * request. If zero, the platform implementation can decided the interface. 287 * 288 * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same 289 * rules as described in `otPlatDnssdRegisterService()`. 290 * 291 * The OpenThread stack will not register the same host (with no changes) that was registered successfully earlier. 292 * Therefore, the platform implementation does not need to check for duplicate/same host and can assume that calls 293 * to this function are either registering a new entry or changing some parameter in a previously registered item. As 294 * a result, these changes always need to be synced on the infrastructure DNS-SD module. 295 * 296 * @param[in] aInstance The OpenThread instance. 297 * @param[in] aHost Information about the host to register. 298 * @param[in] aRequestId The ID associated with this request. 299 * @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed). 300 * 301 */ 302 void otPlatDnssdRegisterHost(otInstance *aInstance, 303 const otPlatDnssdHost *aHost, 304 otPlatDnssdRequestId aRequestId, 305 otPlatDnssdRegisterCallback aCallback); 306 307 /** 308 * Unregisters a host on the infrastructure network's DNS-SD module. 309 * 310 * The @p aHost and all its contained information (strings and arrays) are only valid during this call. The 311 * platform MUST save a copy of the information if it wants to retain the information after returning from this 312 * function. 313 * 314 * The fields in @p aHost follow these rules: 315 * 316 * - The `mHostName` field specifies the host name to unregister. It is never NULL. 317 * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this 318 * request. If zero, the platform implementation can decided the interface. 319 * - The rest of the fields in @p aHost structure MUST be ignored in `otPlatDnssdUnregisterHost()` call and may 320 * be set to zero by the OpenThread stack. 321 * 322 * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same 323 * rules as described in `otPlatDnssdRegisterService()`. 324 * 325 * The OpenThread stack may request the unregistration of a host that was not previously registered, and the platform 326 * implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to indicate 327 * that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. OpenThread stack 328 * will handle either case correctly. 329 * 330 * When unregistering a host, the OpenThread stack will also unregister any previously registered services 331 * associated with the same host (by calling `otPlatDnssdUnregisterService()`). However, the platform implementation 332 * MAY assume that unregistering a host also unregisters all its associated services. 333 * 334 * @param[in] aInstance The OpenThread instance. 335 * @param[in] aHost Information about the host to unregister. 336 * @param[in] aRequestId The ID associated with this request. 337 * @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed). 338 * 339 */ 340 void otPlatDnssdUnregisterHost(otInstance *aInstance, 341 const otPlatDnssdHost *aHost, 342 otPlatDnssdRequestId aRequestId, 343 otPlatDnssdRegisterCallback aCallback); 344 345 /** 346 * Registers or updates a key record on the infrastructure network's DNS-SD module. 347 * 348 * The @p aKey and all its contained information (strings and arrays) are only valid during this call. The 349 * platform MUST save a copy of the information if it wants to retain the information after returning from this 350 * function. 351 * 352 * The fields in @p aKey follow these rules: 353 * 354 * - If the key is associated with a host, `mName` field specifies the host name and `mServiceType` will be NULL. 355 * - If the key is associated with a service, `mName` field specifies the service instance label and `mServiceType` 356 * field specifies the service type. In this case the DNS name for key record is `{mName}.{mServiceTye}`. 357 * - The `mKeyData` field contains the key record's data with `mKeyDataLength` as its length in byes. It is never NULL. 358 * - The `mClass` fields specifies the resource record class to use when registering key record. 359 * - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use. 360 * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this 361 * request. If zero, the platform implementation can decided the interface. 362 * 363 * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same 364 * rules as described in `otPlatDnssdRegisterService()`. 365 * 366 * The OpenThread stack will not register the same key (with no changes) that was registered successfully earlier. 367 * Therefore, the platform implementation does not need to check for duplicate/same name and can assume that calls 368 * to this function are either registering a new key or changing the key data in a previously registered one. As 369 * a result, these changes always need to be synced on the infrastructure DNS-SD module. 370 * 371 * @param[in] aInstance The OpenThread instance. 372 * @param[in] aHost 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 (may be NULL if no callback needed). 375 * 376 */ 377 void otPlatDnssdRegisterKey(otInstance *aInstance, 378 const otPlatDnssdKey *aKey, 379 otPlatDnssdRequestId aRequestId, 380 otPlatDnssdRegisterCallback aCallback); 381 382 /** 383 * Unregisters a key record on the infrastructure network's DNS-SD module. 384 * 385 * The @p aKey and all its contained information (strings and arrays) are only valid during this call. The 386 * platform MUST save a copy of the information if it wants to retain the information after returning from this 387 * function. 388 * 389 * The fields in @p aKey follow these rules: 390 * 391 * - If the key is associated with a host, `mName` field specifies the host name and `mServiceType` will be NULL. 392 * - If the key is associated with a service, `mName` field specifies the service instance label and `mServiceType` 393 * field specifies the service type. In this case the DNS name for key record is `{mName}.{mServiceTye}`. 394 * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this 395 * request. If zero, the platform implementation can decided the interface. 396 * - The rest of the fields in @p aKey structure MUST be ignored in `otPlatDnssdUnregisterKey()` call and may 397 * be set to zero by the OpenThread stack. 398 * 399 * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same 400 * rules as described in `otPlatDnssdRegisterService()`. 401 * 402 * The OpenThread stack may request the unregistration of a key that was not previously registered, and the platform 403 * implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to indicate 404 * that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. the OpenThread 405 * stack will handle either case correctly. 406 * 407 * @param[in] aInstance The OpenThread instance. 408 * @param[in] aKey Information about the key to unregister. 409 * @param[in] aRequestId The ID associated with this request. 410 * @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed). 411 * 412 */ 413 void otPlatDnssdUnregisterKey(otInstance *aInstance, 414 const otPlatDnssdKey *aKey, 415 otPlatDnssdRequestId aRequestId, 416 otPlatDnssdRegisterCallback aCallback); 417 418 /** 419 * @} 420 * 421 */ 422 423 #ifdef __cplusplus 424 } // extern "C" 425 #endif 426 427 #endif // OPENTHREAD_PLATFORM_DNSSD_H_ 428