1 /*
2  *  Copyright (c) 2016, 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 Commissioner role.
33  */
34 
35 #ifndef OPENTHREAD_COMMISSIONER_H_
36 #define OPENTHREAD_COMMISSIONER_H_
37 
38 #include <openthread/dataset.h>
39 #include <openthread/ip6.h>
40 #include <openthread/joiner.h>
41 #include <openthread/platform/radio.h>
42 #include <openthread/platform/toolchain.h>
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 /**
49  * @addtogroup api-commissioner
50  *
51  * @brief
52  *   This module includes functions for the Thread Commissioner role.
53  *
54  * @{
55  */
56 
57 /**
58  * Defines the Commissioner State.
59  */
60 typedef enum otCommissionerState
61 {
62     OT_COMMISSIONER_STATE_DISABLED = 0, ///< Commissioner role is disabled.
63     OT_COMMISSIONER_STATE_PETITION = 1, ///< Currently petitioning to become a Commissioner.
64     OT_COMMISSIONER_STATE_ACTIVE   = 2, ///< Commissioner role is active.
65 } otCommissionerState;
66 
67 /**
68  * Defines a Joiner Event on the Commissioner.
69  */
70 typedef enum otCommissionerJoinerEvent
71 {
72     OT_COMMISSIONER_JOINER_START     = 0,
73     OT_COMMISSIONER_JOINER_CONNECTED = 1,
74     OT_COMMISSIONER_JOINER_FINALIZE  = 2,
75     OT_COMMISSIONER_JOINER_END       = 3,
76     OT_COMMISSIONER_JOINER_REMOVED   = 4,
77 } otCommissionerJoinerEvent;
78 
79 #define OT_COMMISSIONING_PASSPHRASE_MIN_SIZE 6   ///< Minimum size of the Commissioning Passphrase
80 #define OT_COMMISSIONING_PASSPHRASE_MAX_SIZE 255 ///< Maximum size of the Commissioning Passphrase
81 
82 #define OT_PROVISIONING_URL_MAX_SIZE 64 ///< Max size (number of chars) in Provisioning URL string (excludes null char).
83 
84 #define OT_STEERING_DATA_MAX_LENGTH 16 ///< Max steering data length (bytes)
85 
86 /**
87  * Represents the steering data.
88  */
89 typedef struct otSteeringData
90 {
91     uint8_t mLength;                         ///< Length of steering data (bytes)
92     uint8_t m8[OT_STEERING_DATA_MAX_LENGTH]; ///< Byte values
93 } otSteeringData;
94 
95 /**
96  * Represents a Commissioning Dataset.
97  */
98 typedef struct otCommissioningDataset
99 {
100     uint16_t       mLocator;       ///< Border Router RLOC16
101     uint16_t       mSessionId;     ///< Commissioner Session Id
102     otSteeringData mSteeringData;  ///< Steering Data
103     uint16_t       mJoinerUdpPort; ///< Joiner UDP Port
104 
105     bool mIsLocatorSet : 1;       ///< TRUE if Border Router RLOC16 is set, FALSE otherwise.
106     bool mIsSessionIdSet : 1;     ///< TRUE if Commissioner Session Id is set, FALSE otherwise.
107     bool mIsSteeringDataSet : 1;  ///< TRUE if Steering Data is set, FALSE otherwise.
108     bool mIsJoinerUdpPortSet : 1; ///< TRUE if Joiner UDP Port is set, FALSE otherwise.
109     bool mHasExtraTlv : 1;        ///< TRUE if the Dataset contains any extra unknown sub-TLV, FALSE otherwise.
110 } otCommissioningDataset;
111 
112 #define OT_JOINER_MAX_PSKD_LENGTH 32 ///< Maximum string length of a Joiner PSKd (does not include null char).
113 
114 /**
115  * Represents a Joiner PSKd.
116  */
117 typedef struct otJoinerPskd
118 {
119     char m8[OT_JOINER_MAX_PSKD_LENGTH + 1]; ///< Char string array (must be null terminated - +1 is for null char).
120 } otJoinerPskd;
121 
122 /**
123  * Defines a Joiner Info Type.
124  */
125 typedef enum otJoinerInfoType
126 {
127     OT_JOINER_INFO_TYPE_ANY       = 0, ///< Accept any Joiner (no EUI64 or Discerner is specified).
128     OT_JOINER_INFO_TYPE_EUI64     = 1, ///< Joiner EUI-64 is specified (`mSharedId.mEui64` in `otJoinerInfo`).
129     OT_JOINER_INFO_TYPE_DISCERNER = 2, ///< Joiner Discerner is specified (`mSharedId.mDiscerner` in `otJoinerInfo`).
130 } otJoinerInfoType;
131 
132 /**
133  * Represents a Joiner Info.
134  */
135 typedef struct otJoinerInfo
136 {
137     otJoinerInfoType mType; ///< Joiner type.
138     union
139     {
140         otExtAddress      mEui64;     ///< Joiner EUI64 (when `mType` is `OT_JOINER_INFO_TYPE_EUI64`)
141         otJoinerDiscerner mDiscerner; ///< Joiner Discerner (when `mType` is `OT_JOINER_INFO_TYPE_DISCERNER`)
142     } mSharedId;                      ///< Shared fields
143     otJoinerPskd mPskd;               ///< Joiner PSKd
144     uint32_t     mExpirationTime;     ///< Joiner expiration time in msec
145 } otJoinerInfo;
146 
147 /**
148  * Pointer is called whenever the commissioner state changes.
149  *
150  * @param[in]  aState    The Commissioner state.
151  * @param[in]  aContext  A pointer to application-specific context.
152  */
153 typedef void (*otCommissionerStateCallback)(otCommissionerState aState, void *aContext);
154 
155 /**
156  * Pointer is called whenever the joiner state changes.
157  *
158  * @param[in]  aEvent       The joiner event type.
159  * @param[in]  aJoinerInfo  A pointer to the Joiner Info.
160  * @param[in]  aJoinerId    A pointer to the Joiner ID (if not known, it will be NULL).
161  * @param[in]  aContext     A pointer to application-specific context.
162  */
163 typedef void (*otCommissionerJoinerCallback)(otCommissionerJoinerEvent aEvent,
164                                              const otJoinerInfo       *aJoinerInfo,
165                                              const otExtAddress       *aJoinerId,
166                                              void                     *aContext);
167 
168 /**
169  * Enables the Thread Commissioner role.
170  *
171  * @param[in]  aInstance         A pointer to an OpenThread instance.
172  * @param[in]  aStateCallback    A pointer to a function that is called when the commissioner state changes.
173  * @param[in]  aJoinerCallback   A pointer to a function that is called with a joiner event occurs.
174  * @param[in]  aCallbackContext  A pointer to application-specific context.
175  *
176  * @retval OT_ERROR_NONE           Successfully started the Commissioner service.
177  * @retval OT_ERROR_ALREADY        Commissioner is already started.
178  * @retval OT_ERROR_INVALID_STATE  Device is not currently attached to a network.
179  */
180 otError otCommissionerStart(otInstance                  *aInstance,
181                             otCommissionerStateCallback  aStateCallback,
182                             otCommissionerJoinerCallback aJoinerCallback,
183                             void                        *aCallbackContext);
184 
185 /**
186  * Disables the Thread Commissioner role.
187  *
188  * @param[in]  aInstance         A pointer to an OpenThread instance.
189  *
190  * @retval OT_ERROR_NONE     Successfully stopped the Commissioner service.
191  * @retval OT_ERROR_ALREADY  Commissioner is already stopped.
192  */
193 otError otCommissionerStop(otInstance *aInstance);
194 
195 /**
196  * Returns the Commissioner Id.
197  *
198  * @param[in]  aInstance         A pointer to an OpenThread instance.
199  *
200  * @returns The Commissioner Id.
201  */
202 const char *otCommissionerGetId(otInstance *aInstance);
203 
204 /**
205  * Sets the Commissioner Id.
206  *
207  * @param[in]  aInstance     A pointer to an OpenThread instance.
208  * @param[in]  aId           A pointer to a string character array. Must be null terminated.
209  *
210  * @retval OT_ERROR_NONE            Successfully set the Commissioner Id.
211  * @retval OT_ERROR_INVALID_ARGS    Given name is too long.
212  * @retval OT_ERROR_INVALID_STATE   The commissioner is active and id cannot be changed.
213  */
214 otError otCommissionerSetId(otInstance *aInstance, const char *aId);
215 
216 /**
217  * Adds a Joiner entry.
218  *
219  * @param[in]  aInstance          A pointer to an OpenThread instance.
220  * @param[in]  aEui64             A pointer to the Joiner's IEEE EUI-64 or NULL for any Joiner.
221  * @param[in]  aPskd              A pointer to the PSKd.
222  * @param[in]  aTimeout           A time after which a Joiner is automatically removed, in seconds.
223  *
224  * @retval OT_ERROR_NONE          Successfully added the Joiner.
225  * @retval OT_ERROR_NO_BUFS       No buffers available to add the Joiner.
226  * @retval OT_ERROR_INVALID_ARGS  @p aEui64 or @p aPskd is invalid.
227  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
228  *
229  * @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
230  */
231 otError otCommissionerAddJoiner(otInstance         *aInstance,
232                                 const otExtAddress *aEui64,
233                                 const char         *aPskd,
234                                 uint32_t            aTimeout);
235 
236 /**
237  * Adds a Joiner entry with a given Joiner Discerner value.
238  *
239  * @param[in]  aInstance          A pointer to an OpenThread instance.
240  * @param[in]  aDiscerner         A pointer to the Joiner Discerner.
241  * @param[in]  aPskd              A pointer to the PSKd.
242  * @param[in]  aTimeout           A time after which a Joiner is automatically removed, in seconds.
243  *
244  * @retval OT_ERROR_NONE          Successfully added the Joiner.
245  * @retval OT_ERROR_NO_BUFS       No buffers available to add the Joiner.
246  * @retval OT_ERROR_INVALID_ARGS  @p aDiscerner or @p aPskd is invalid.
247  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
248  *
249  * @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
250  */
251 otError otCommissionerAddJoinerWithDiscerner(otInstance              *aInstance,
252                                              const otJoinerDiscerner *aDiscerner,
253                                              const char              *aPskd,
254                                              uint32_t                 aTimeout);
255 
256 /**
257  * Get joiner info at aIterator position.
258  *
259  * @param[in]      aInstance   A pointer to instance.
260  * @param[in,out]  aIterator   A pointer to the Joiner Info iterator context.
261  * @param[out]     aJoiner     A reference to Joiner info.
262  *
263  * @retval OT_ERROR_NONE       Successfully get the Joiner info.
264  * @retval OT_ERROR_NOT_FOUND  Not found next Joiner.
265  */
266 otError otCommissionerGetNextJoinerInfo(otInstance *aInstance, uint16_t *aIterator, otJoinerInfo *aJoiner);
267 
268 /**
269  * Removes a Joiner entry.
270  *
271  * @param[in]  aInstance          A pointer to an OpenThread instance.
272  * @param[in]  aEui64             A pointer to the Joiner's IEEE EUI-64 or NULL for any Joiner.
273  *
274  * @retval OT_ERROR_NONE          Successfully removed the Joiner.
275  * @retval OT_ERROR_NOT_FOUND     The Joiner specified by @p aEui64 was not found.
276  * @retval OT_ERROR_INVALID_ARGS  @p aEui64 is invalid.
277  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
278  *
279  * @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
280  */
281 otError otCommissionerRemoveJoiner(otInstance *aInstance, const otExtAddress *aEui64);
282 
283 /**
284  * Removes a Joiner entry.
285  *
286  * @param[in]  aInstance          A pointer to an OpenThread instance.
287  * @param[in]  aDiscerner         A pointer to the Joiner Discerner.
288  *
289  * @retval OT_ERROR_NONE          Successfully removed the Joiner.
290  * @retval OT_ERROR_NOT_FOUND     The Joiner specified by @p aEui64 was not found.
291  * @retval OT_ERROR_INVALID_ARGS  @p aDiscerner is invalid.
292  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
293  *
294  * @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
295  */
296 otError otCommissionerRemoveJoinerWithDiscerner(otInstance *aInstance, const otJoinerDiscerner *aDiscerner);
297 
298 /**
299  * Gets the Provisioning URL.
300  *
301  * @param[in]    aInstance       A pointer to an OpenThread instance.
302  *
303  * @returns A pointer to the URL string.
304  */
305 const char *otCommissionerGetProvisioningUrl(otInstance *aInstance);
306 
307 /**
308  * Sets the Provisioning URL.
309  *
310  * @param[in]  aInstance             A pointer to an OpenThread instance.
311  * @param[in]  aProvisioningUrl      A pointer to the Provisioning URL (may be NULL to set as empty string).
312  *
313  * @retval OT_ERROR_NONE          Successfully set the Provisioning URL.
314  * @retval OT_ERROR_INVALID_ARGS  @p aProvisioningUrl is invalid (too long).
315  */
316 otError otCommissionerSetProvisioningUrl(otInstance *aInstance, const char *aProvisioningUrl);
317 
318 /**
319  * Sends an Announce Begin message.
320  *
321  * @param[in]  aInstance             A pointer to an OpenThread instance.
322  * @param[in]  aChannelMask          The channel mask value.
323  * @param[in]  aCount                The number of Announcement messages per channel.
324  * @param[in]  aPeriod               The time between two successive MLE Announce transmissions (in milliseconds).
325  * @param[in]  aAddress              A pointer to the IPv6 destination.
326  *
327  * @retval OT_ERROR_NONE          Successfully enqueued the Announce Begin message.
328  * @retval OT_ERROR_NO_BUFS       Insufficient buffers to generate an Announce Begin message.
329  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
330  *
331  * @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
332  */
333 otError otCommissionerAnnounceBegin(otInstance         *aInstance,
334                                     uint32_t            aChannelMask,
335                                     uint8_t             aCount,
336                                     uint16_t            aPeriod,
337                                     const otIp6Address *aAddress);
338 
339 /**
340  * Pointer is called when the Commissioner receives an Energy Report.
341  *
342  * @param[in]  aChannelMask       The channel mask value.
343  * @param[in]  aEnergyList        A pointer to the energy measurement list.
344  * @param[in]  aEnergyListLength  Number of entries in @p aEnergyListLength.
345  * @param[in]  aContext           A pointer to application-specific context.
346  */
347 typedef void (*otCommissionerEnergyReportCallback)(uint32_t       aChannelMask,
348                                                    const uint8_t *aEnergyList,
349                                                    uint8_t        aEnergyListLength,
350                                                    void          *aContext);
351 
352 /**
353  * Sends an Energy Scan Query message.
354  *
355  * @param[in]  aInstance             A pointer to an OpenThread instance.
356  * @param[in]  aChannelMask          The channel mask value.
357  * @param[in]  aCount                The number of energy measurements per channel.
358  * @param[in]  aPeriod               The time between energy measurements (milliseconds).
359  * @param[in]  aScanDuration         The scan duration for each energy measurement (milliseconds).
360  * @param[in]  aAddress              A pointer to the IPv6 destination.
361  * @param[in]  aCallback             A pointer to a function called on receiving an Energy Report message.
362  * @param[in]  aContext              A pointer to application-specific context.
363  *
364  * @retval OT_ERROR_NONE          Successfully enqueued the Energy Scan Query message.
365  * @retval OT_ERROR_NO_BUFS       Insufficient buffers to generate an Energy Scan Query message.
366  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
367  *
368  * @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
369  */
370 otError otCommissionerEnergyScan(otInstance                        *aInstance,
371                                  uint32_t                           aChannelMask,
372                                  uint8_t                            aCount,
373                                  uint16_t                           aPeriod,
374                                  uint16_t                           aScanDuration,
375                                  const otIp6Address                *aAddress,
376                                  otCommissionerEnergyReportCallback aCallback,
377                                  void                              *aContext);
378 
379 /**
380  * Pointer is called when the Commissioner receives a PAN ID Conflict message.
381  *
382  * @param[in]  aPanId             The PAN ID value.
383  * @param[in]  aChannelMask       The channel mask value.
384  * @param[in]  aContext           A pointer to application-specific context.
385  */
386 typedef void (*otCommissionerPanIdConflictCallback)(uint16_t aPanId, uint32_t aChannelMask, void *aContext);
387 
388 /**
389  * Sends a PAN ID Query message.
390  *
391  * @param[in]  aInstance             A pointer to an OpenThread instance.
392  * @param[in]  aPanId                The PAN ID to query.
393  * @param[in]  aChannelMask          The channel mask value.
394  * @param[in]  aAddress              A pointer to the IPv6 destination.
395  * @param[in]  aCallback             A pointer to a function called on receiving a PAN ID Conflict message.
396  * @param[in]  aContext              A pointer to application-specific context.
397  *
398  * @retval OT_ERROR_NONE          Successfully enqueued the PAN ID Query message.
399  * @retval OT_ERROR_NO_BUFS       Insufficient buffers to generate a PAN ID Query message.
400  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
401  *
402  * @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
403  */
404 otError otCommissionerPanIdQuery(otInstance                         *aInstance,
405                                  uint16_t                            aPanId,
406                                  uint32_t                            aChannelMask,
407                                  const otIp6Address                 *aAddress,
408                                  otCommissionerPanIdConflictCallback aCallback,
409                                  void                               *aContext);
410 
411 /**
412  * Sends MGMT_COMMISSIONER_GET.
413  *
414  * @param[in]  aInstance  A pointer to an OpenThread instance.
415  * @param[in]  aTlvs      A pointer to TLVs.
416  * @param[in]  aLength    The length of TLVs.
417  *
418  * @retval OT_ERROR_NONE          Successfully send the meshcop dataset command.
419  * @retval OT_ERROR_NO_BUFS       Insufficient buffer space to send.
420  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
421  */
422 otError otCommissionerSendMgmtGet(otInstance *aInstance, const uint8_t *aTlvs, uint8_t aLength);
423 
424 /**
425  * Sends MGMT_COMMISSIONER_SET.
426  *
427  * @param[in]  aInstance  A pointer to an OpenThread instance.
428  * @param[in]  aDataset   A pointer to commissioning dataset.
429  * @param[in]  aTlvs      A pointer to TLVs.
430  * @param[in]  aLength    The length of TLVs.
431  *
432  * @retval OT_ERROR_NONE          Successfully send the meshcop dataset command.
433  * @retval OT_ERROR_NO_BUFS       Insufficient buffer space to send.
434  * @retval OT_ERROR_INVALID_STATE The commissioner is not active.
435  */
436 otError otCommissionerSendMgmtSet(otInstance                   *aInstance,
437                                   const otCommissioningDataset *aDataset,
438                                   const uint8_t                *aTlvs,
439                                   uint8_t                       aLength);
440 
441 /**
442  * Returns the Commissioner Session ID.
443  *
444  * @param[in]  aInstance  A pointer to an OpenThread instance.
445  *
446  * @returns The current commissioner session id.
447  */
448 uint16_t otCommissionerGetSessionId(otInstance *aInstance);
449 
450 /**
451  * Returns the Commissioner State.
452  *
453  * @param[in]  aInstance  A pointer to an OpenThread instance.
454  *
455  * @retval OT_COMMISSIONER_STATE_DISABLED  Commissioner disabled.
456  * @retval OT_COMMISSIONER_STATE_PETITION  Becoming the commissioner.
457  * @retval OT_COMMISSIONER_STATE_ACTIVE    Commissioner enabled.
458  */
459 otCommissionerState otCommissionerGetState(otInstance *aInstance);
460 
461 /**
462  * @}
463  */
464 
465 #ifdef __cplusplus
466 } // end of extern "C"
467 #endif
468 
469 #endif // OPENTHREAD_COMMISSIONER_H_
470