1 /* 2 * Copyright (c) 2018, 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 functions for the Thread Border Agent role. 33 */ 34 35 #ifndef OPENTHREAD_BORDER_AGENT_H_ 36 #define OPENTHREAD_BORDER_AGENT_H_ 37 38 #include <openthread/instance.h> 39 #include <openthread/ip6.h> 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 /** 46 * @addtogroup api-border-agent 47 * 48 * @brief 49 * This module includes functions for the Thread Border Agent role. 50 * 51 * @{ 52 */ 53 54 /** 55 * The length of Border Agent/Router ID in bytes. 56 */ 57 #define OT_BORDER_AGENT_ID_LENGTH (16) 58 59 /** 60 * Represents a Border Agent Identifier. 61 */ 62 typedef struct otBorderAgentId 63 { 64 uint8_t mId[OT_BORDER_AGENT_ID_LENGTH]; ///< Border Agent ID bytes. 65 } otBorderAgentId; 66 67 /** 68 * Defines Border Agent counters. 69 * 70 * The `mEpskc` related counters require `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`. 71 */ 72 typedef struct otBorderAgentCounters 73 { 74 uint32_t mEpskcActivations; ///< The number of ePSKc activations 75 uint32_t mEpskcDeactivationClears; ///< The number of ePSKc deactivations via API 76 uint32_t mEpskcDeactivationTimeouts; ///< The number of ePSKc deactivations due to timeout 77 uint32_t mEpskcDeactivationMaxAttempts; ///< The number of ePSKc deactivations due to reached max attempts 78 uint32_t mEpskcDeactivationDisconnects; ///< The number of ePSKc deactivations due to commissioner disconnected 79 uint32_t mEpskcInvalidBaStateErrors; ///< The number of invalid border agent state errors at ePSKc activation 80 uint32_t mEpskcInvalidArgsErrors; ///< The number of invalid args errors at ePSKc activation 81 uint32_t mEpskcStartSecureSessionErrors; ///< The number of start secure session errors at ePSKc activation 82 uint32_t mEpskcSecureSessionSuccesses; ///< The number of established secure sessions with ePSKc 83 uint32_t mEpskcSecureSessionFailures; ///< The number of failed secure sessions with ePSKc 84 uint32_t mEpskcCommissionerPetitions; ///< The number of successful commissioner petitions with ePSKc 85 uint32_t mPskcSecureSessionSuccesses; ///< The number of established secure sessions with PSKc 86 uint32_t mPskcSecureSessionFailures; ///< The number of failed secure sessions with PSKc 87 uint32_t mPskcCommissionerPetitions; ///< The number of successful commissioner petitions with PSKc 88 uint32_t mMgmtActiveGets; ///< The number of MGMT_ACTIVE_GET.req sent over secure sessions 89 uint32_t mMgmtPendingGets; ///< The number of MGMT_PENDING_GET.req sent over secure sessions 90 } otBorderAgentCounters; 91 92 /** 93 * Represents information about a Border Agent session. 94 * 95 * This structure is populated by `otBorderAgentGetNextSessionInfo()` during iteration over the list of sessions using 96 * an `otBorderAgentSessionIterator`. 97 * 98 * To ensure consistent `mLifetime` calculations, the iterator's initialization time is stored within the iterator, 99 * and each session's `mLifetime` is calculated relative to this time. 100 */ 101 typedef struct otBorderAgentSessionInfo 102 { 103 otSockAddr mPeerSockAddr; ///< Socket address (IPv6 address and port number) of session peer. 104 bool mIsConnected; ///< Indicates whether the session is connected. 105 bool mIsCommissioner; ///< Indicates whether the session is accepted as full commissioner. 106 uint64_t mLifetime; ///< Milliseconds since the session was first established. 107 } otBorderAgentSessionInfo; 108 109 /** 110 * Represents an iterator for Border Agent sessions. 111 * 112 * The caller MUST NOT access or update the fields in this struct. It is intended for OpenThread internal use only. 113 */ 114 typedef struct otBorderAgentSessionIterator 115 { 116 void *mPtr; 117 uint64_t mData; 118 } otBorderAgentSessionIterator; 119 120 #define OT_BORDER_AGENT_MESHCOP_SERVICE_TXT_DATA_MAX_LENGTH 128 121 122 /** 123 * Represents the Border Agent MeshCoP Service TXT data. 124 */ 125 typedef struct otBorderAgentMeshCoPServiceTxtData 126 { 127 uint8_t mData[OT_BORDER_AGENT_MESHCOP_SERVICE_TXT_DATA_MAX_LENGTH]; 128 uint16_t mLength; 129 } otBorderAgentMeshCoPServiceTxtData; 130 131 /** 132 * Indicates whether or not the Border Agent service is active and running. 133 * 134 * While the Border Agent is active, external commissioner candidates can try to connect to and establish secure DTLS 135 * sessions with the Border Agent using PSKc. A connected commissioner can then petition to become a full commissioner. 136 * 137 * If `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE` is enabled, independent and separate DTLS transport and 138 * sessions are used for the ephemeral key. Therefore, the ephemeral key and Border Agent service can be enabled and 139 * used in parallel. 140 * 141 * @param[in] aInstance A pointer to an OpenThread instance. 142 * 143 * @retval TRUE The Border Agent is active. 144 * @retval FALSE The Border Agent is not active. 145 */ 146 bool otBorderAgentIsActive(otInstance *aInstance); 147 148 /** 149 * Gets the UDP port of the Thread Border Agent service. 150 * 151 * @param[in] aInstance A pointer to an OpenThread instance. 152 * 153 * @returns UDP port of the Border Agent. 154 */ 155 uint16_t otBorderAgentGetUdpPort(otInstance *aInstance); 156 157 /** 158 * This callback informs the application of the changes in the state of the MeshCoP service. 159 * 160 * In specific, the 'state' includes the MeshCoP TXT data originated from the Thread network and whether the 161 * Border Agent is Active (which can be obtained by `otBorderAgentIsActive`). 162 * 163 * @param[in] aContext A pointer to application-specific context. 164 */ 165 typedef void (*otBorderAgentMeshCoPServiceChangedCallback)(void *aContext); 166 167 /** 168 * Sets the callback function used by the Border Agent to notify of any changes to the state of the MeshCoP service. 169 * 170 * The callback is invoked when the 'Is Active' state of the Border Agent or the MeshCoP service TXT data values 171 * change. For example, it is invoked when the network name or the extended PAN ID changes and passes the updated 172 * encoded TXT data to the application layer. 173 * 174 * This callback is invoked once right after this API is called to provide initial states of the MeshCoP service. 175 * 176 * @param[in] aInstance A pointer to an OpenThread instance. 177 * @param[in] aCallback The callback to be invoked when there are any changes of the MeshCoP service. 178 * @param[in] aContext A pointer to application-specific context. 179 */ 180 void otBorderAgentSetMeshCoPServiceChangedCallback(otInstance *aInstance, 181 otBorderAgentMeshCoPServiceChangedCallback aCallback, 182 void *aContext); 183 184 /** 185 * Gets the MeshCoP service TXT data. 186 * 187 * @param[in] aInstance A pointer to an OpenThread instance. 188 * @param[out] aTxtData A pointer to a MeshCoP Service TXT data struct to get the data. 189 * 190 * @retval OT_ERROR_NONE If successfully retrieved the Border Agent MeshCoP Service TXT data. 191 * @retval OT_ERROR_NO_BUFS If the buffer in @p aTxtData doesn't have enough size. 192 */ 193 otError otBorderAgentGetMeshCoPServiceTxtData(otInstance *aInstance, otBorderAgentMeshCoPServiceTxtData *aTxtData); 194 195 /** 196 * Gets the randomly generated Border Agent ID. 197 * 198 * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE`. 199 * 200 * The ID is saved in persistent storage and survives reboots. The typical use case of the ID is to 201 * be published in the MeshCoP mDNS service as the `id` TXT value for the client to identify this 202 * Border Router/Agent device. 203 * 204 * @param[in] aInstance A pointer to an OpenThread instance. 205 * @param[out] aId A pointer to buffer to receive the ID. 206 * 207 * @retval OT_ERROR_NONE If successfully retrieved the Border Agent ID. 208 * @retval ... If failed to retrieve the Border Agent ID. 209 * 210 * @sa otBorderAgentSetId 211 */ 212 otError otBorderAgentGetId(otInstance *aInstance, otBorderAgentId *aId); 213 214 /** 215 * Sets the Border Agent ID. 216 * 217 * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE`. 218 * 219 * The Border Agent ID will be saved in persistent storage and survive reboots. It's required to 220 * set the ID only once after factory reset. If the ID has never been set by calling this function, 221 * a random ID will be generated and returned when `otBorderAgentGetId` is called. 222 * 223 * @param[in] aInstance A pointer to an OpenThread instance. 224 * @param[out] aId A pointer to the Border Agent ID. 225 * 226 * @retval OT_ERROR_NONE If successfully set the Border Agent ID. 227 * @retval ... If failed to set the Border Agent ID. 228 * 229 * @sa otBorderAgentGetId 230 */ 231 otError otBorderAgentSetId(otInstance *aInstance, const otBorderAgentId *aId); 232 233 /** 234 * Initializes a session iterator. 235 * 236 * An iterator MUST be initialized before being used in `otBorderAgentGetNextSessionInfo()`. A previously initialized 237 * iterator can be re-initialized to start from the beginning of the session list. 238 * 239 * @param[in] aInstance A pointer to an OpenThread instance. 240 * @param[in] aIterator The iterator to initialize. 241 */ 242 void otBorderAgentInitSessionIterator(otInstance *aInstance, otBorderAgentSessionIterator *aIterator); 243 244 /** 245 * Retrieves the next Border Agent session information. 246 * 247 * @param[in] aIterator The iterator to use. 248 * @param[out] aSessionInfo A pointer to an `otBorderAgentSessionInfo` to populate. 249 * 250 * @retval OT_ERROR_NONE Successfully retrieved the next session info. 251 * @retval OT_ERROR_NOT_FOUND No more sessions are available. The end of the list has been reached. 252 */ 253 otError otBorderAgentGetNextSessionInfo(otBorderAgentSessionIterator *aIterator, 254 otBorderAgentSessionInfo *aSessionInfo); 255 256 /** 257 * Gets the counters of the Thread Border Agent. 258 * 259 * @param[in] aInstance A pointer to an OpenThread instance. 260 * 261 * @returns A pointer to the Border Agent counters. 262 */ 263 const otBorderAgentCounters *otBorderAgentGetCounters(otInstance *aInstance); 264 265 /*-------------------------------------------------------------------------------------------------------------------- 266 * Border Agent Ephemeral Key feature */ 267 268 /** 269 * Minimum length of the ephemeral key string. 270 */ 271 #define OT_BORDER_AGENT_MIN_EPHEMERAL_KEY_LENGTH (6) 272 273 /** 274 * Maximum length of the ephemeral key string. 275 */ 276 #define OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_LENGTH (32) 277 278 /** 279 * Default ephemeral key timeout interval in milliseconds. 280 */ 281 #define OT_BORDER_AGENT_DEFAULT_EPHEMERAL_KEY_TIMEOUT (2 * 60 * 1000u) 282 283 /** 284 * Maximum ephemeral key timeout interval in milliseconds. 285 */ 286 #define OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_TIMEOUT (10 * 60 * 1000u) 287 288 /** 289 * Represents Border Agent's Ephemeral Key Manager state. 290 */ 291 typedef enum otBorderAgentEphemeralKeyState 292 { 293 OT_BORDER_AGENT_STATE_DISABLED = 0, ///< Ephemeral Key Manager is disabled. 294 OT_BORDER_AGENT_STATE_STOPPED = 1, ///< Enabled, but no ephemeral key is in use (not set or started). 295 OT_BORDER_AGENT_STATE_STARTED = 2, ///< Ephemeral key is set. Listening to accept secure connections. 296 OT_BORDER_AGENT_STATE_CONNECTED = 3, ///< Session is established with an external commissioner candidate. 297 OT_BORDER_AGENT_STATE_ACCEPTED = 4, ///< Session is established and candidate is accepted as full commissioner. 298 } otBorderAgentEphemeralKeyState; 299 300 /** 301 * Gets the state of Border Agent's Ephemeral Key Manager. 302 * 303 * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`. 304 * 305 * @param[in] aInstance A pointer to an OpenThread instance. 306 * 307 * @returns The current state of Ephemeral Key Manager. 308 */ 309 otBorderAgentEphemeralKeyState otBorderAgentEphemeralKeyGetState(otInstance *aInstance); 310 311 /** 312 * Enables/disables the Border Agent's Ephemeral Key Manager. 313 * 314 * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`. 315 * 316 * If this function is called to disable, while an an ephemeral key is in use, the ephemeral key use will be stopped 317 * (as if `otBorderAgentEphemeralKeyStop()` is called). 318 * 319 * @param[in] aInstance The OpenThread instance. 320 * @param[in] aEnabled Whether to enable or disable the Ephemeral Key Manager. 321 */ 322 void otBorderAgentEphemeralKeySetEnabled(otInstance *aInstance, bool aEnabled); 323 324 /** 325 * Starts using an ephemeral key for a given timeout duration. 326 * 327 * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`. 328 * 329 * An ephemeral key can only be set when `otBorderAgentEphemeralKeyGetState()` is `OT_BORDER_AGENT_STATE_STOPPED`, 330 * i.e., enabled but not yet started. Otherwise, `OT_ERROR_INVALID_STATE` is returned. This means that setting the 331 * ephemeral key again while a previously set key is still in use will fail. Callers can stop the previous key by 332 * calling `otBorderAgentEphemeralKeyStop()` before starting with a new key. 333 * 334 * The Ephemeral Key Manager and the Border Agent service (which uses PSKc) can be enabled and used in parallel, as 335 * they use independent and separate DTLS transport and sessions. 336 * 337 * The given @p aKeyString is used directly as the ephemeral PSK (excluding the trailing null `\0` character). 338 * Its length must be between `OT_BORDER_AGENT_MIN_EPHEMERAL_KEY_LENGTH` and `OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_LENGTH`, 339 * inclusive. Otherwise `OT_ERROR_INVALID_ARGS` is returned. 340 * 341 * When successfully set, the ephemeral key can be used only once by an external commissioner candidate to establish a 342 * secure session. After the commissioner candidate disconnects, the use of the ephemeral key is stopped. If the 343 * timeout expires, the use of the ephemeral key is stopped, and any connected session using the key is immediately 344 * disconnected. 345 * 346 * The Ephemeral Key Manager limits the number of failed DTLS connections to 10 attempts. After the 10th failed 347 * attempt, the use of the ephemeral key is automatically stopped (even if the timeout has not yet expired). 348 * 349 * @param[in] aInstance The OpenThread instance. 350 * @param[in] aKeyString The ephemeral key. 351 * @param[in] aTimeout The timeout duration, in milliseconds, to use the ephemeral key. 352 * If zero, the default `OT_BORDER_AGENT_DEFAULT_EPHEMERAL_KEY_TIMEOUT` value is used. If the 353 * timeout value is larger than `OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_TIMEOUT`, the maximum value 354 * is used instead. 355 * @param[in] aUdpPort The UDP port to use with the ephemeral key. If the UDP port is zero, an ephemeral port will 356 * be used. `otBorderAgentEphemeralKeyGetUdpPort()` returns the current UDP port being used. 357 * 358 * @retval OT_ERROR_NONE Successfully started using the ephemeral key. 359 * @retval OT_ERROR_INVALID_STATE A previously set ephemeral key is still in use or the feature is disabled. 360 * @retval OT_ERROR_INVALID_ARGS The given @p aKeyString is not valid. 361 * @retval OT_ERROR_FAILED Failed to start (e.g., it could not bind to the given UDP port). 362 */ 363 otError otBorderAgentEphemeralKeyStart(otInstance *aInstance, 364 const char *aKeyString, 365 uint32_t aTimeout, 366 uint16_t aUdpPort); 367 368 /** 369 * Stops the ephemeral key use and disconnects any session using it. 370 * 371 * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`. 372 * 373 * If there is no ephemeral key in use, calling this function has no effect. 374 * 375 * @param[in] aInstance The OpenThread instance. 376 */ 377 void otBorderAgentEphemeralKeyStop(otInstance *aInstance); 378 379 /** 380 * Gets the UDP port used by Border Agent's Ephemeral Key Manager. 381 * 382 * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`. 383 * 384 * The port is applicable if an ephemeral key is in use, i.e., the state is not `OT_BORDER_AGENT_STATE_DISABLED` or 385 * `OT_BORDER_AGENT_STATE_STOPPED`. 386 * 387 * @param[in] aInstance A pointer to an OpenThread instance. 388 * 389 * @returns The UDP port being used by Border Agent's Ephemeral Key Manager (when active). 390 */ 391 uint16_t otBorderAgentEphemeralKeyGetUdpPort(otInstance *aInstance); 392 393 /** 394 * Callback function pointer to signal state changes to the Border Agent's Ephemeral Key Manager. 395 * 396 * This callback is invoked whenever the `otBorderAgentEphemeralKeyGetState()` gets changed. 397 * 398 * Any OpenThread API, including `otBorderAgent` APIs, can be safely called from this callback. 399 * 400 * @param[in] aContext A pointer to an arbitrary context (provided when callback is set). 401 */ 402 typedef void (*otBorderAgentEphemeralKeyCallback)(void *aContext); 403 404 /** 405 * Sets the callback function to notify state changes of Border Agent's Ephemeral Key Manager. 406 * 407 * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`. 408 * 409 * A subsequent call to this function will replace any previously set callback. 410 * 411 * @param[in] aInstance The OpenThread instance. 412 * @param[in] aCallback The callback function pointer. 413 * @param[in] aContext The arbitrary context to use with callback. 414 */ 415 void otBorderAgentEphemeralKeySetCallback(otInstance *aInstance, 416 otBorderAgentEphemeralKeyCallback aCallback, 417 void *aContext); 418 419 /** 420 * Converts a given `otBorderAgentEphemeralKeyState` to a human-readable string. 421 * 422 * @param[in] aState The state to convert. 423 * 424 * @returns Human-readable string corresponding to @p aState. 425 */ 426 const char *otBorderAgentEphemeralKeyStateToString(otBorderAgentEphemeralKeyState aState); 427 428 /** 429 * @} 430 */ 431 432 #ifdef __cplusplus 433 } // end of extern "C" 434 #endif 435 436 #endif // OPENTHREAD_BORDER_AGENT_H_ 437