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