• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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