1 /* 2 * Copyright (c) 2020, 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 #ifndef SRP_CLIENT_HPP_ 30 #define SRP_CLIENT_HPP_ 31 32 #include "openthread-core-config.h" 33 34 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 35 36 #include <openthread/srp_client.h> 37 38 #include "common/as_core_type.hpp" 39 #include "common/clearable.hpp" 40 #include "common/linked_list.hpp" 41 #include "common/locator.hpp" 42 #include "common/log.hpp" 43 #include "common/message.hpp" 44 #include "common/non_copyable.hpp" 45 #include "common/notifier.hpp" 46 #include "common/numeric_limits.hpp" 47 #include "common/timer.hpp" 48 #include "crypto/ecdsa.hpp" 49 #include "net/dns_types.hpp" 50 #include "net/ip6.hpp" 51 #include "net/udp6.hpp" 52 #include "thread/network_data_service.hpp" 53 54 /** 55 * @file 56 * This file includes definitions for the SRP (Service Registration Protocol) client. 57 */ 58 59 namespace ot { 60 namespace Srp { 61 62 #if !OPENTHREAD_CONFIG_ECDSA_ENABLE 63 #error "SRP Client feature requires ECDSA support (OPENTHREAD_CONFIG_ECDSA_ENABLE)." 64 #endif 65 66 /** 67 * This class implements SRP client. 68 * 69 */ 70 class Client : public InstanceLocator, private NonCopyable 71 { 72 friend class ot::Notifier; 73 74 using DnsSrpUnicast = NetworkData::Service::DnsSrpUnicast; 75 using DnsSrpAnycast = NetworkData::Service::DnsSrpAnycast; 76 77 public: 78 /** 79 * This enumeration types represents an SRP client item (service or host info) state. 80 * 81 */ 82 enum ItemState : uint8_t 83 { 84 kToAdd = OT_SRP_CLIENT_ITEM_STATE_TO_ADD, ///< Item to be added/registered. 85 kAdding = OT_SRP_CLIENT_ITEM_STATE_ADDING, ///< Item is being added/registered. 86 kToRefresh = OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH, ///< Item to be refreshed (renew lease). 87 kRefreshing = OT_SRP_CLIENT_ITEM_STATE_REFRESHING, ///< Item is being refreshed. 88 kToRemove = OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE, ///< Item to be removed. 89 kRemoving = OT_SRP_CLIENT_ITEM_STATE_REMOVING, ///< Item is being removed. 90 kRegistered = OT_SRP_CLIENT_ITEM_STATE_REGISTERED, ///< Item is registered with server. 91 kRemoved = OT_SRP_CLIENT_ITEM_STATE_REMOVED, ///< Item is removed. 92 }; 93 94 /** 95 * This function pointer type defines the callback used by SRP client to notify user of a changes/events/errors. 96 * 97 * Please see `otSrpClientCallback` for more details. 98 * 99 */ 100 typedef otSrpClientCallback Callback; 101 102 /** 103 * This type represents an SRP client host info. 104 * 105 */ 106 class HostInfo : public otSrpClientHostInfo, private Clearable<HostInfo> 107 { 108 friend class Client; 109 110 public: 111 /** 112 * This method initializes the `HostInfo` object. 113 * 114 */ 115 void Init(void); 116 117 /** 118 * This method clears the `HostInfo` object. 119 * 120 */ 121 void Clear(void); 122 123 /** 124 * This method gets the host name (label) string. 125 * 126 * @returns The host name (label) string, or `nullptr` if not yet set. 127 * 128 */ GetName(void) const129 const char *GetName(void) const { return mName; } 130 131 /** 132 * This method indicates whether or not the host auto address mode is enabled. 133 * 134 * @retval TRUE If the auto address mode is enabled. 135 * @retval FALSE If the auto address mode is disabled. 136 * 137 */ IsAutoAddressEnabled(void) const138 bool IsAutoAddressEnabled(void) const { return mAutoAddress; } 139 140 /** 141 * This method gets the number of host IPv6 addresses. 142 * 143 * @returns The number of host IPv6 addresses. 144 * 145 */ GetNumAddresses(void) const146 uint8_t GetNumAddresses(void) const { return mNumAddresses; } 147 148 /** 149 * This method gets the host IPv6 address at a given index. 150 * 151 * @param[in] aIndex The index to get (MUST be smaller than `GetNumAddresses()`). 152 * 153 * @returns The host IPv6 address at index @p aIndex. 154 * 155 */ GetAddress(uint8_t aIndex) const156 const Ip6::Address &GetAddress(uint8_t aIndex) const { return AsCoreType(&mAddresses[aIndex]); } 157 158 /** 159 * This method gets the state of `HostInfo`. 160 * 161 * @returns The `HostInfo` state. 162 * 163 */ GetState(void) const164 ItemState GetState(void) const { return static_cast<ItemState>(mState); } 165 166 private: SetName(const char * aName)167 void SetName(const char *aName) { mName = aName; } 168 void SetState(ItemState aState); 169 void SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses); 170 void EnableAutoAddress(void); 171 }; 172 173 /** 174 * This type represents an SRP client service. 175 * 176 */ 177 class Service : public otSrpClientService, public LinkedListEntry<Service> 178 { 179 friend class Client; 180 friend class LinkedList<Service>; 181 182 public: 183 /** 184 * This method initializes and validates the `Service` object and its fields. 185 * 186 * @retval kErrorNone Successfully initialized and validated the `Service` object. 187 * @retval kErrorInvalidArgs The info in `Service` object is not valid (e.g. null name or bad `TxtEntry`). 188 * 189 */ 190 Error Init(void); 191 192 /** 193 * This method gets the service name labels string. 194 * 195 * @returns The service name label string (e.g., "_chip._udp", not the full domain name). 196 * 197 */ GetName(void) const198 const char *GetName(void) const { return mName; } 199 200 /** 201 * This method gets the service instance name label (not the full name). 202 * 203 * @returns The service instance name label string. 204 * 205 */ GetInstanceName(void) const206 const char *GetInstanceName(void) const { return mInstanceName; } 207 208 /** 209 * This method indicates whether or not the service has any subtypes. 210 * 211 * @retval TRUE The service has at least one subtype. 212 * @retval FALSE The service does not have any subtype. 213 * 214 */ HasSubType(void) const215 bool HasSubType(void) const { return (mSubTypeLabels != nullptr); } 216 217 /** 218 * This method gets the subtype label at a given index. 219 * 220 * This method MUST be used only after `HasSubType()` indicates that service has a subtype. 221 * 222 * @param[in] aIndex The index into list of subtype labels. 223 * 224 * @returns A pointer to subtype label at @p aIndex, or `nullptr` if there is no label (@p aIndex is after the 225 * end of the subtype list). 226 * 227 */ GetSubTypeLabelAt(uint16_t aIndex) const228 const char *GetSubTypeLabelAt(uint16_t aIndex) const { return mSubTypeLabels[aIndex]; } 229 230 /** 231 * This method gets the service port number. 232 * 233 * @returns The service port number. 234 * 235 */ GetPort(void) const236 uint16_t GetPort(void) const { return mPort; } 237 238 /** 239 * This method gets the service priority. 240 * 241 * @returns The service priority. 242 * 243 */ GetPriority(void) const244 uint16_t GetPriority(void) const { return mPriority; } 245 246 /** 247 * This method gets the service weight. 248 * 249 * @returns The service weight. 250 * 251 */ GetWeight(void) const252 uint16_t GetWeight(void) const { return mWeight; } 253 254 /** 255 * This method gets the array of service TXT entries. 256 * 257 * @returns A pointer to an array of service TXT entries. 258 * 259 */ GetTxtEntries(void) const260 const Dns::TxtEntry *GetTxtEntries(void) const { return AsCoreTypePtr(mTxtEntries); } 261 262 /** 263 * This method gets the number of entries in the service TXT entry array. 264 * 265 * @returns The number of entries in the service TXT entry array. 266 * 267 */ GetNumTxtEntries(void) const268 uint8_t GetNumTxtEntries(void) const { return mNumTxtEntries; } 269 270 /** 271 * This method get the state of service. 272 * 273 * @returns The service state. 274 * 275 */ GetState(void) const276 ItemState GetState(void) const { return static_cast<ItemState>(mState); } 277 278 private: 279 void SetState(ItemState aState); GetLeaseRenewTime(void) const280 TimeMilli GetLeaseRenewTime(void) const { return TimeMilli(mData); } SetLeaseRenewTime(TimeMilli aTime)281 void SetLeaseRenewTime(TimeMilli aTime) { mData = aTime.GetValue(); } 282 bool Matches(const Service &aOther) const; Matches(ItemState aState) const283 bool Matches(ItemState aState) const { return GetState() == aState; } 284 }; 285 286 /** 287 * This constructor initializes the SRP `Client` object. 288 * 289 * @param[in] aInstance A reference to the OpenThread instance. 290 * 291 */ 292 explicit Client(Instance &aInstance); 293 294 /** 295 * This method starts the SRP client operation. 296 * 297 * SRP client will prepare and send "SRP Update" message to the SRP server once all the following conditions are 298 * met: 299 * 300 * - The SRP client is started - `Start()` is called 301 * - Host name is set - `SetHostName()` is called. 302 * - At least one host IPv6 address is set - `SetHostAddresses()` is called. 303 * - At least one service is added - `AddService()` is called. 304 * 305 * It does not matter in which order these methods are called. When all conditions are met, the SRP client will 306 * wait for a short delay before preparing an "SRP Update" message and sending it to server. This delay allows for 307 * user to add multiple services and/or IPv6 addresses before the first SRP Update message is sent (ensuring a 308 * single SRP Update is sent containing all the info). 309 * 310 * @param[in] aServerSockAddr The socket address (IPv6 address and port number) of the SRP server. 311 * 312 * @retval kErrorNone SRP client operation started successfully or it is already running with same server 313 * socket address and callback. 314 * @retval kErrorBusy SRP client is busy running with a different socket address. 315 * @retval kErrorFailed Failed to open/connect the client's UDP socket. 316 * 317 */ Start(const Ip6::SockAddr & aServerSockAddr)318 Error Start(const Ip6::SockAddr &aServerSockAddr) { return Start(aServerSockAddr, kRequesterUser); } 319 320 /** 321 * This method stops the SRP client operation. 322 * 323 * This method stops any further interactions with the SRP server. Note that it does not remove or clear host info 324 * and/or list of services. It marks all services to be added/removed again once the client is started again. 325 * 326 * If `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` (auto-start feature) is enabled, a call to this method 327 * also disables the auto-start mode. 328 * 329 */ Stop(void)330 void Stop(void) { Stop(kRequesterUser, kResetRetryInterval); } 331 332 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE 333 /** 334 * This function pointer type defines the callback used by SRP client to notify user when it is auto-started or 335 * stopped. 336 * 337 */ 338 typedef otSrpClientAutoStartCallback AutoStartCallback; 339 340 /** 341 * This method enables the auto-start mode. 342 * 343 * Config option `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE` specifies the default auto-start mode 344 * (whether it is enabled or disabled at the start of OT stack). 345 * 346 * When auto-start is enabled, the SRP client will monitor the Thread Network Data for SRP Server Service entries 347 * and automatically start and stop the client when an SRP server is detected. 348 * 349 * If multiple SRP servers are found, a random one will be selected. If the selected SRP server is no longer 350 * detected (not longer present in the Thread Network Data), the SRP client will be stopped and then it may switch 351 * to another SRP server (if available). 352 * 353 * When the SRP client is explicitly started through a successful call to `Start()`, the given SRP server address 354 * in `Start()` will continue to be used regardless of the state of auto-start mode and whether the same SRP 355 * server address is discovered or not in the Thread Network Data. In this case, only an explicit `Stop()` call 356 * will stop the client. 357 * 358 * @param[in] aCallback A callback to notify when client is auto-started/stopped. Can be `nullptr` if not needed. 359 * @param[in] aContext A context to be passed when invoking @p aCallback. 360 * 361 */ 362 void EnableAutoStartMode(AutoStartCallback aCallback, void *aContext); 363 364 /** 365 * This method disables the auto-start mode. 366 * 367 * Disabling the auto-start mode will not stop the client if it is already running but the client stops monitoring 368 * the Thread Network Data to verify that the selected SRP server is still present in it. 369 * 370 * Note that a call to `Stop()` will also disable the auto-start mode. 371 * 372 */ DisableAutoStartMode(void)373 void DisableAutoStartMode(void) { mAutoStart.SetState(AutoStart::kDisabled); } 374 375 /** 376 * This method indicates the current state of auto-start mode (enabled or disabled). 377 * 378 * @returns TRUE if the auto-start mode is enabled, FALSE otherwise. 379 * 380 */ IsAutoStartModeEnabled(void) const381 bool IsAutoStartModeEnabled(void) const { return mAutoStart.GetState() != AutoStart::kDisabled; } 382 383 /** 384 * This method indicates whether or not the current SRP server's address is selected by auto-start. 385 * 386 * @returns TRUE if the SRP server's address is selected by auto-start, FALSE otherwise. 387 * 388 */ IsServerSelectedByAutoStart(void) const389 bool IsServerSelectedByAutoStart(void) const { return mAutoStart.HasSelectedServer(); } 390 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE 391 392 /** 393 * This method indicates whether the SRP client is running or not. 394 * 395 * @returns TRUE if the SRP client is running, FALSE otherwise. 396 * 397 */ IsRunning(void) const398 bool IsRunning(void) const { return (mState != kStateStopped); } 399 400 /** 401 * This method gets the socket address (IPv6 address and port number) of the SRP server which is being used by SRP 402 * client. 403 * 404 * If the client is not running, the address is unspecified (all zero) with zero port number. 405 * 406 * @returns The SRP server's socket address. 407 * 408 */ GetServerAddress(void) const409 const Ip6::SockAddr &GetServerAddress(void) const { return mSocket.GetPeerName(); } 410 411 /** 412 * This method sets the callback used to notify caller of events/changes. 413 * 414 * The SRP client allows a single callback to be registered. So consecutive calls to this method will overwrite any 415 * previously set callback functions. 416 * 417 * @param[in] aCallback The callback to notify of events and changes. Can be `nullptr` if not needed. 418 * @param[in] aContext An arbitrary context used with @p aCallback. 419 * 420 */ 421 void SetCallback(Callback aCallback, void *aContext); 422 423 /** 424 * This method gets the TTL used in SRP update requests. 425 * 426 * Note that this is the TTL requested by the SRP client. The server may choose to accept a different TTL. 427 * 428 * By default, the TTL will equal the lease interval. Passing 0 or a value larger than the lease interval via 429 * `otSrpClientSetTtl()` will also cause the TTL to equal the lease interval. 430 * 431 * @returns The TTL (in seconds). 432 * 433 */ GetTtl(void) const434 uint32_t GetTtl(void) const { return (0 < mTtl && mTtl < mLeaseInterval) ? mTtl : mLeaseInterval; } 435 436 /** 437 * This method sets the TTL used in SRP update requests. 438 * 439 * Changing the TTL does not impact the TTL of already registered services/host-info. 440 * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services). 441 * 442 * @param[in] aTtl The TTL (in seconds). If value is zero or greater than lease interval, the TTL is set to the 443 * lease interval. 444 * 445 */ SetTtl(uint32_t aTtl)446 void SetTtl(uint32_t aTtl) { mTtl = aTtl; } 447 448 /** 449 * This method gets the lease interval used in SRP update requests. 450 * 451 * Note that this is lease duration that would be requested by the SRP client. Server may choose to accept a 452 * different lease interval. 453 * 454 * @returns The lease interval (in seconds). 455 * 456 */ GetLeaseInterval(void) const457 uint32_t GetLeaseInterval(void) const { return mLeaseInterval; } 458 459 /** 460 * This method sets the lease interval used in SRP update requests. 461 * 462 * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info. 463 * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services). 464 * 465 * @param[in] aInterval The lease interval (in seconds). If zero, the default value `kDefaultLease` would be used. 466 * 467 */ SetLeaseInterval(uint32_t aInterval)468 void SetLeaseInterval(uint32_t aInterval) { mLeaseInterval = GetBoundedLeaseInterval(aInterval, kDefaultLease); } 469 470 /** 471 * This method gets the key lease interval used in SRP update requests. 472 * 473 * @returns The key lease interval (in seconds). 474 * 475 */ GetKeyLeaseInterval(void) const476 uint32_t GetKeyLeaseInterval(void) const { return mKeyLeaseInterval; } 477 478 /** 479 * This method sets the key lease interval used in SRP update requests. 480 * 481 * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info. 482 * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services). 483 * 484 * @param[in] aInterval The key lease interval (in seconds). If zero, the default value `kDefaultKeyLease` would be 485 * used. 486 * 487 */ SetKeyLeaseInterval(uint32_t aInterval)488 void SetKeyLeaseInterval(uint32_t aInterval) 489 { 490 mKeyLeaseInterval = GetBoundedLeaseInterval(aInterval, kDefaultKeyLease); 491 } 492 493 /** 494 * This method gets the host info. 495 * 496 * @returns A reference to host info structure. 497 * 498 */ GetHostInfo(void) const499 const HostInfo &GetHostInfo(void) const { return mHostInfo; } 500 501 /** 502 * This method sets the host name label. 503 * 504 * After a successful call to this method, `Callback` will be called to report the status of host info 505 * registration with SRP server. 506 * 507 * The host name can be set before client is started or after start but before host info is registered with server 508 * (host info should be in either `kToAdd` or `kRemoved`). 509 * 510 * @param[in] aName A pointer to host name label string (MUST NOT be NULL). Pointer the string buffer MUST 511 * persist and remain valid and constant after return from this method. 512 * 513 * @retval kErrorNone The host name label was set successfully. 514 * @retval kErrorInvalidArgs The @p aName is NULL. 515 * @retval kErrorInvalidState The host name is already set and registered with the server. 516 * 517 */ 518 Error SetHostName(const char *aName); 519 520 /** 521 * This method enables auto host address mode. 522 * 523 * When enabled host IPv6 addresses are automatically set by SRP client using all the unicast addresses on Thread 524 * netif excluding the link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID 525 * address is added. The SRP client will automatically re-register when/if addresses on Thread netif are updated 526 * (new addresses are added or existing addresses are removed). 527 * 528 * The auto host address mode can be enabled before start or during operation of SRP client except when the host 529 * info is being removed (client is busy handling a remove request from an call to `RemoveHostAndServices()` and 530 * host info still being in either `kStateToRemove` or `kStateRemoving` states). 531 * 532 * After auto host address mode is enabled, it can be disabled by a call to `SetHostAddresses()` which then 533 * explicitly sets the host addresses. 534 * 535 * @retval kErrorNone Successfully enabled auto host address mode. 536 * @retval kErrorInvalidState Host is being removed and therefore cannot enable auto host address mode. 537 * 538 */ 539 Error EnableAutoHostAddress(void); 540 541 /** 542 * This method sets/updates the list of host IPv6 address. 543 * 544 * Host IPv6 addresses can be set/changed before start or even during operation of SRP client (e.g. to add/remove 545 * or change a previously registered host address), except when the host info is being removed (client is busy 546 * handling a remove request from an earlier call to `RemoveHostAndServices()` and host info still being in either 547 * `kStateToRemove` or `kStateRemoving` states). 548 * 549 * After a successful call to this method, `Callback` will be called to report the status of the address 550 * registration with SRP server. 551 * 552 * Calling this method disables auto host address mode if it was previously enabled from a successful call to 553 * `EnableAutoHostAddress()`. 554 * 555 * @param[in] aAddresses A pointer to the an array containing the host IPv6 addresses. 556 * @param[in] aNumAddresses The number of addresses in the @p aAddresses array. 557 * 558 * @retval kErrorNone The host IPv6 address list change started successfully. The `Callback` will be 559 * called to report the status of registering addresses with server. 560 * @retval kErrorInvalidArgs The address list is invalid (e.g., must contain at least one address). 561 * @retval kErrorInvalidState Host is being removed and therefore cannot change host address. 562 * 563 */ 564 Error SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses); 565 566 /** 567 * This method adds a service to be registered with server. 568 * 569 * After a successful call to this method, `Callback` will be called to report the status of the service 570 * addition/registration with SRP server. 571 * 572 * @param[in] aService A `Service` to add (the instance must persist and remain unchanged after 573 * successful return from this method). 574 * 575 * @retval kErrorNone The addition of service started successfully. The `Callback` will be called to 576 * report the status. 577 * @retval kErrorAlready A service with the same service and instance names is already in the list. 578 * @retval kErrorInvalidArgs The service structure is invalid (e.g., bad service name or `TxEntry`). 579 * 580 */ 581 Error AddService(Service &aService); 582 583 /** 584 * This method removes a service to be unregistered with server. 585 * 586 * @param[in] aService A `Service` to remove (the instance must persist and remain unchanged after 587 * successful return from this method). 588 * 589 * @retval kErrorNone The removal of service started successfully. The `Callback` will be called to report 590 * the status. 591 * @retval kErrorNotFound The service could not be found in the list. 592 * 593 */ 594 595 Error RemoveService(Service &aService); 596 597 /** 598 * This method clears a service, immediately removing it from the client service list. 599 * 600 * Unlike `RemoveService()` which sends an update message to the server to remove the service, this method clears 601 * the service from the client's service list without any interaction with the server. On a successful call 602 * to this method, the `Callback` will NOT be called and the @p aService entry can be reclaimed and re-used by the 603 * caller immediately. 604 * 605 * @param[in] aService A service to delete from the list. 606 * 607 * @retval kErrorNone The @p aService is cleared successfully. It can be reclaimed and re-used immediately. 608 * @retval kErrorNotFound The service could not be found in the list. 609 * 610 */ 611 Error ClearService(Service &aService); 612 613 /** 614 * This method gets the list of services being managed by client. 615 * 616 * @returns The list of services. 617 * 618 */ GetServices(void) const619 const LinkedList<Service> &GetServices(void) const { return mServices; } 620 621 /** 622 * This method starts the remove process of the host info and all services. 623 * 624 * After returning from this method, `Callback` will be called to report the status of remove request with 625 * SRP server. 626 * 627 * If the host info is to be permanently removed from server, @p aRemoveKeyLease should be set to `true` which 628 * removes the key lease associated with host on server. Otherwise, the key lease record is kept as before, which 629 * ensures that the server holds the host name in reserve for when the client once again able to provide and 630 * register its service(s). 631 * 632 * The @p aSendUnregToServer determines the behavior when the host info is not yet registered with the server. If 633 * @p aSendUnregToServer is set to `false` (which is the default/expected value) then the SRP client will 634 * immediately remove the host info and services without sending an update message to server (no need to update the 635 * server if nothing is yet registered with it). If @p aSendUnregToServer is set to `true` then the SRP client will 636 * send an update message to the server. Note that if the host info is registered then the value of 637 * @p aSendUnregToServer does not matter and the SRP client will always send an update message to server requesting 638 * removal of all info. 639 * 640 * One situation where @p aSendUnregToServer can be useful is on a device reset/reboot, caller may want to remove 641 * any previously registered services with the server. In this case, caller can `SetHostName()` and then request 642 * `RemoveHostAndServices()` with `aSendUnregToServer` as `true`. 643 * 644 * @param[in] aShouldRemoveKeyLease A boolean indicating whether or not the host key lease should also be removed. 645 * @param[in] aSendUnregToServer A boolean indicating whether to send update to server when host info is not 646 * registered. 647 * 648 * @retval kErrorNone The removal of host and services started successfully. The `Callback` will be called 649 * to report the status. 650 * @retval kErrorAlready The host is already removed. 651 * 652 */ 653 Error RemoveHostAndServices(bool aShouldRemoveKeyLease, bool aSendUnregToServer = false); 654 655 /** 656 * This method clears all host info and all the services. 657 * 658 * Unlike `RemoveHostAndServices()` which sends an update message to the server to remove all the info, this method 659 * clears all the info immediately without any interaction with the server. 660 * 661 */ 662 void ClearHostAndServices(void); 663 664 #if OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE 665 /** 666 * This method gets the domain name being used by SRP client. 667 * 668 * If domain name is not set, "default.service.arpa" will be used. 669 * 670 * @returns The domain name string. 671 * 672 */ GetDomainName(void) const673 const char *GetDomainName(void) const { return mDomainName; } 674 675 /** 676 * This method sets the domain name to be used by SRP client. 677 * 678 * This is an optional method. If not set "default.service.arpa" will be used. 679 * 680 * The domain name can be set before client is started or after start but before host info is registered with server 681 * (host info should be in either `kToAdd` or `kToRemove`). 682 * 683 * @param[in] aName A pointer to the domain name string. If NULL sets it to default "default.service.arpa". 684 * 685 * @retval kErrorNone The domain name label was set successfully. 686 * @retval kErrorInvalidState The host info is already registered with server. 687 * 688 */ 689 Error SetDomainName(const char *aName); 690 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE 691 692 /** 693 * This static method converts a `ItemState` to a string. 694 * 695 * @param[in] aState An `ItemState`. 696 * 697 * @returns A string representation of @p aState. 698 * 699 */ 700 static const char *ItemStateToString(ItemState aState); 701 702 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 703 /** 704 * This method enables/disables "service key record inclusion" mode. 705 * 706 * When enabled, SRP client will include KEY record in Service Description Instructions in the SRP update messages 707 * that it sends. 708 * 709 * @note KEY record is optional in Service Description Instruction (it is required and always included in the Host 710 * Description Instruction). The default behavior of SRP client is to not include it. This method is added under 711 * `REFERENCE_DEVICE` config and is intended to override the default behavior for testing only. 712 * 713 * @param[in] aEnabled TRUE to enable, FALSE to disable the "service key record inclusion" mode. 714 * 715 */ SetServiceKeyRecordEnabled(bool aEnabled)716 void SetServiceKeyRecordEnabled(bool aEnabled) { mServiceKeyRecordEnabled = aEnabled; } 717 718 /** 719 * This method indicates whether the "service key record inclusion" mode is enabled or disabled. 720 * 721 * @returns TRUE if "service key record inclusion" mode is enabled, FALSE otherwise. 722 * 723 */ IsServiceKeyRecordEnabled(void) const724 bool IsServiceKeyRecordEnabled(void) const { return mServiceKeyRecordEnabled; } 725 #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 726 727 private: 728 // Number of fast data polls after SRP Update tx (11x 188ms = ~2 seconds) 729 static constexpr uint8_t kFastPollsAfterUpdateTx = 11; 730 731 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE 732 static constexpr uint8_t kMaxTimeoutFailuresToSwitchServer = 733 OPENTHREAD_CONFIG_SRP_CLIENT_MAX_TIMEOUT_FAILURES_TO_SWITCH_SERVER; 734 #endif 735 736 static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header); 737 738 // ------------------------------- 739 // Lease related constants 740 741 static constexpr uint32_t kDefaultLease = OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_LEASE; // in seconds. 742 static constexpr uint32_t kDefaultKeyLease = OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_KEY_LEASE; // in seconds. 743 744 // The guard interval determines how much earlier (relative to 745 // the lease expiration time) the client will send an update 746 // to renew the lease. Value is in seconds. 747 static constexpr uint32_t kLeaseRenewGuardInterval = OPENTHREAD_CONFIG_SRP_CLIENT_LEASE_RENEW_GUARD_INTERVAL; 748 749 // Max allowed lease time to avoid timer roll-over (~24.8 days). 750 static constexpr uint32_t kMaxLease = (Timer::kMaxDelay / 1000) - 1; 751 752 // Opportunistic early refresh: When sending an SRP update, the 753 // services that are not yet expired but are close, are allowed 754 // to refresh early and are included in the SRP update. This 755 // helps place more services on the same lease refresh schedule 756 // reducing number of messages sent to the SRP server. The 757 // "early lease renewal interval" is used to determine if a 758 // service can renew early. The interval is calculated by 759 // multiplying the accepted lease interval by the"early lease 760 // renewal factor" which is given as a fraction (numerator and 761 // denominator). 762 // 763 // If the factor is set to zero (numerator=0, denominator=1), 764 // the opportunistic early refresh behavior is disabled. If 765 // denominator is set to zero (the factor is set to infinity), 766 // then all services (including previously registered ones) 767 // are always included in SRP update message. 768 769 static constexpr uint32_t kEarlyLeaseRenewFactorNumerator = 770 OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_NUMERATOR; 771 static constexpr uint32_t kEarlyLeaseRenewFactorDenominator = 772 OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR; 773 774 // ------------------------------- 775 // When there is a change (e.g., a new service is added/removed) 776 // that requires an update, the SRP client will wait for a short 777 // delay as specified by `kUpdateTxDelay` before sending an SRP 778 // update to server. This allows the user to provide more change 779 // that are then all sent in same update message. 780 static constexpr uint32_t kUpdateTxMinDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY; // in msec. 781 static constexpr uint32_t kUpdateTxMaxDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY; // in msec. 782 783 // ------------------------------- 784 // Retry related constants 785 // 786 // If the preparation or transmission of an SRP update message 787 // fails (e.g., no buffer to allocate the message), SRP client 788 // will retry after a short interval `kTxFailureRetryInterval` 789 // up to `kMaxTxFailureRetries` attempts. After this, the retry 790 // wait interval will be used (which keeps growing on each failure 791 // - please see bellow). 792 // 793 // If the update message is sent successfully but there is no 794 // response from server or if server rejects the update, the 795 // client will retransmit the update message after some wait 796 // interval. The wait interval starts from the minimum value and 797 // is increased by the growth factor on back-to-back failures up 798 // to the max value. The growth factor is given as a fraction 799 // (e.g., for 1.5, we can use 15 as the numerator and 10 as the 800 // denominator). A random jitter is added to the retry interval. 801 // If the current wait interval value is smaller than the jitter 802 // interval, then wait interval value itself is used as the 803 // jitter value. For example, with jitter interval of 2 seconds 804 // if the current retry interval is 800ms, then a random wait 805 // interval in [0,2*800] ms will be used. 806 807 static constexpr uint32_t kTxFailureRetryInterval = 250; // in ms 808 static constexpr uint32_t kMaxTxFailureRetries = 8; // num of quick retries after tx failure 809 static constexpr uint32_t kMinRetryWaitInterval = OPENTHREAD_CONFIG_SRP_CLIENT_MIN_RETRY_WAIT_INTERVAL; // in ms 810 static constexpr uint32_t kMaxRetryWaitInterval = OPENTHREAD_CONFIG_SRP_CLIENT_MAX_RETRY_WAIT_INTERVAL; // in ms 811 static constexpr uint32_t kRetryIntervalGrowthFactorNumerator = 812 OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_NUMERATOR; 813 static constexpr uint32_t kRetryIntervalGrowthFactorDenominator = 814 OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_DENOMINATOR; 815 816 static constexpr uint16_t kTxFailureRetryJitter = 10; // in ms 817 static constexpr uint16_t kRetryIntervalJitter = OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_WAIT_INTERVAL_JITTER; // in ms 818 819 static_assert(kDefaultLease <= static_cast<uint32_t>(kMaxLease), "kDefaultLease is larger than max"); 820 static_assert(kDefaultKeyLease <= static_cast<uint32_t>(kMaxLease), "kDefaultKeyLease is larger than max"); 821 822 enum State : uint8_t 823 { 824 kStateStopped, // Client is stopped. 825 kStatePaused, // Client is paused (due to device being detached). 826 kStateToUpdate, // Waiting to send SRP update 827 kStateUpdating, // SRP update is sent, waiting for response from server. 828 kStateUpdated, // SRP update response received from server. 829 kStateToRetry, // SRP update tx failed, waiting to retry. 830 }; 831 832 static constexpr bool kAutoStartDefaultMode = OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE; 833 static constexpr bool kDisallowSwitchOnRegisteredHost = 834 OPENTHREAD_CONFIG_SRP_CLIENT_DISALLOW_SERVER_SWITCH_WITH_REGISTERED_HOST; 835 836 // Port number to use when server is discovered using "network data anycast service". 837 static constexpr uint16_t kAnycastServerPort = 53; 838 839 // This enumeration type is used by the private `Start()` and 840 // `Stop()` methods to indicate whether it is being requested by the 841 // user or by the auto-start feature. 842 enum Requester : uint8_t 843 { 844 kRequesterUser, 845 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE 846 kRequesterAuto, 847 #endif 848 }; 849 850 // This enumeration is used as an input to private `Stop()` to 851 // indicate whether to reset the retry interval or keep it as is. 852 enum StopMode : uint8_t 853 { 854 kResetRetryInterval, 855 kKeepRetryInterval, 856 }; 857 858 class SingleServiceMode 859 { 860 public: SingleServiceMode(void)861 SingleServiceMode(void) 862 : mEnabled(false) 863 , mService(nullptr) 864 { 865 } 866 Enable(void)867 void Enable(void) { mEnabled = true, mService = nullptr; } Disable(void)868 void Disable(void) { mEnabled = false; } IsEnabled(void) const869 bool IsEnabled(void) const { return mEnabled; } GetService(void)870 Service *GetService(void) { return mService; } SetService(Service & aService)871 void SetService(Service &aService) { mService = &aService; } 872 873 private: 874 bool mEnabled; 875 Service *mService; 876 }; 877 878 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE 879 class AutoStart : Clearable<AutoStart> 880 { 881 public: 882 enum State : uint8_t{ 883 kDisabled, // AutoStart is disabled. 884 kSelectedNone, // AutoStart is enabled but not yet selected any servers. 885 kSelectedUnicastPreferred, // AutoStart selected a preferred unicast entry (address in service data). 886 kSelectedAnycast, // AutoStart selected an anycast entry with `mAnycastSeqNum`. 887 kSelectedUnicast, // AutoStart selected a unicast entry (address in server data). 888 }; 889 890 AutoStart(void); 891 bool HasSelectedServer(void) const; GetState(void) const892 State GetState(void) const { return mState; } 893 void SetState(State aState); GetAnycastSeqNum(void) const894 uint8_t GetAnycastSeqNum(void) const { return mAnycastSeqNum; } SetAnycastSeqNum(uint8_t aAnycastSeqNum)895 void SetAnycastSeqNum(uint8_t aAnycastSeqNum) { mAnycastSeqNum = aAnycastSeqNum; } 896 void SetCallback(AutoStartCallback aCallback, void *aContext); 897 void InvokeCallback(const Ip6::SockAddr *aServerSockAddr) const; 898 899 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE GetTimoutFailureCount(void) const900 uint8_t GetTimoutFailureCount(void) const { return mTimoutFailureCount; } ResetTimoutFailureCount(void)901 void ResetTimoutFailureCount(void) { mTimoutFailureCount = 0; } IncrementTimoutFailureCount(void)902 void IncrementTimoutFailureCount(void) 903 { 904 if (mTimoutFailureCount < NumericLimits<uint8_t>::kMax) 905 { 906 mTimoutFailureCount++; 907 } 908 } 909 #endif 910 911 private: 912 static constexpr bool kDefaultMode = OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE; 913 914 static const char *StateToString(State aState); 915 916 AutoStartCallback mCallback; 917 void * mContext; 918 State mState; 919 uint8_t mAnycastSeqNum; 920 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE 921 uint8_t mTimoutFailureCount; // Number of no-response timeout failures with the currently selected server. 922 #endif 923 }; 924 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE 925 926 struct Info : public Clearable<Info> 927 { 928 static constexpr uint16_t kUnknownOffset = 0; // Unknown offset value (used when offset is not yet set). 929 930 uint16_t mDomainNameOffset; // Offset of domain name serialization 931 uint16_t mHostNameOffset; // Offset of host name serialization. 932 uint16_t mRecordCount; // Number of resource records in Update section. 933 Crypto::Ecdsa::P256::KeyPair mKeyPair; // The ECDSA key pair. 934 }; 935 936 Error Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester); 937 void Stop(Requester aRequester, StopMode aMode); 938 void Resume(void); 939 void Pause(void); 940 void HandleNotifierEvents(Events aEvents); 941 void HandleRoleChanged(void); 942 Error UpdateHostInfoStateOnAddressChange(void); 943 void UpdateServiceStateToRemove(Service &aService); GetState(void) const944 State GetState(void) const { return mState; } 945 void SetState(State aState); 946 void ChangeHostAndServiceStates(const ItemState *aNewStates); 947 void InvokeCallback(Error aError) const; 948 void InvokeCallback(Error aError, const HostInfo &aHostInfo, const Service *aRemovedServices) const; 949 void HandleHostInfoOrServiceChange(void); 950 void SendUpdate(void); 951 Error PrepareUpdateMessage(Message &aMessage); 952 Error ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair); 953 Error AppendServiceInstructions(Service &aService, Message &aMessage, Info &aInfo); 954 Error AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo); 955 Error AppendKeyRecord(Message &aMessage, Info &aInfo) const; 956 Error AppendDeleteAllRrsets(Message &aMessage) const; 957 Error AppendHostName(Message &aMessage, Info &aInfo, bool aDoNotCompress = false) const; 958 Error AppendAaaaRecord(const Ip6::Address &aAddress, Message &aMessage, Info &aInfo) const; 959 Error AppendUpdateLeaseOptRecord(Message &aMessage) const; 960 Error AppendSignature(Message &aMessage, Info &aInfo); 961 void UpdateRecordLengthInMessage(Dns::ResourceRecord &aRecord, uint16_t aOffset, Message &aMessage) const; 962 static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); 963 void ProcessResponse(Message &aMessage); 964 void HandleUpdateDone(void); 965 void GetRemovedServices(LinkedList<Service> &aRemovedServices); 966 static Error ReadResourceRecord(const Message &aMessage, uint16_t &aOffset, Dns::ResourceRecord &aRecord); 967 Error ProcessOptRecord(const Message &aMessage, uint16_t aOffset, const Dns::OptRecord &aOptRecord); 968 void UpdateState(void); GetRetryWaitInterval(void) const969 uint32_t GetRetryWaitInterval(void) const { return mRetryWaitInterval; } ResetRetryWaitInterval(void)970 void ResetRetryWaitInterval(void) { mRetryWaitInterval = kMinRetryWaitInterval; } 971 void GrowRetryWaitInterval(void); 972 uint32_t GetBoundedLeaseInterval(uint32_t aInterval, uint32_t aDefaultInterval) const; 973 bool ShouldRenewEarly(const Service &aService) const; 974 static void HandleTimer(Timer &aTimer); 975 void HandleTimer(void); 976 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE 977 void ProcessAutoStart(void); 978 Error SelectUnicastEntry(DnsSrpUnicast::Origin aOrigin, DnsSrpUnicast::Info &aInfo) const; 979 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE 980 void SelectNextServer(bool aDisallowSwitchOnRegisteredHost); 981 #endif 982 #endif 983 984 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) 985 static const char *StateToString(State aState); 986 void LogRetryWaitInterval(void) const; 987 #else LogRetryWaitInterval(void) const988 void LogRetryWaitInterval(void) const {} 989 #endif 990 991 static const char kDefaultDomainName[]; 992 993 static_assert(kMaxTxFailureRetries < 16, "kMaxTxFailureRetries exceed the range of mTxFailureRetryCount (4-bit)"); 994 995 State mState; 996 uint8_t mTxFailureRetryCount : 4; 997 bool mShouldRemoveKeyLease : 1; 998 bool mAutoHostAddressAddedMeshLocal : 1; 999 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 1000 bool mServiceKeyRecordEnabled : 1; 1001 #endif 1002 1003 uint16_t mUpdateMessageId; 1004 uint32_t mRetryWaitInterval; 1005 1006 TimeMilli mLeaseRenewTime; 1007 uint32_t mAcceptedLeaseInterval; 1008 uint32_t mTtl; 1009 uint32_t mLeaseInterval; 1010 uint32_t mKeyLeaseInterval; 1011 1012 Ip6::Udp::Socket mSocket; 1013 1014 Callback mCallback; 1015 void * mCallbackContext; 1016 const char * mDomainName; 1017 HostInfo mHostInfo; 1018 LinkedList<Service> mServices; 1019 SingleServiceMode mSingleServiceMode; 1020 TimerMilli mTimer; 1021 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE 1022 AutoStart mAutoStart; 1023 #endif 1024 }; 1025 1026 } // namespace Srp 1027 1028 DefineCoreType(otSrpClientHostInfo, Srp::Client::HostInfo); 1029 DefineCoreType(otSrpClientService, Srp::Client::Service); 1030 DefineMapEnum(otSrpClientItemState, Srp::Client::ItemState); 1031 1032 } // namespace ot 1033 1034 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1035 1036 #endif // SRP_CLIENT_HPP_ 1037