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 * This file includes definitions for the Joiner role. 32 */ 33 34 #ifndef JOINER_HPP_ 35 #define JOINER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #if OPENTHREAD_CONFIG_JOINER_ENABLE 40 41 #include <openthread/joiner.h> 42 43 #include "coap/coap.hpp" 44 #include "coap/coap_message.hpp" 45 #include "coap/coap_secure.hpp" 46 #include "common/locator.hpp" 47 #include "common/logging.hpp" 48 #include "common/message.hpp" 49 #include "common/non_copyable.hpp" 50 #include "mac/mac_types.hpp" 51 #include "meshcop/dtls.hpp" 52 #include "meshcop/meshcop.hpp" 53 #include "meshcop/meshcop_tlvs.hpp" 54 #include "thread/discover_scanner.hpp" 55 56 namespace ot { 57 58 namespace MeshCoP { 59 60 class Joiner : public InstanceLocator, private NonCopyable 61 { 62 public: 63 /** 64 * This enumeration type defines the Joiner State. 65 * 66 */ 67 enum State : uint8_t 68 { 69 kStateIdle = OT_JOINER_STATE_IDLE, 70 kStateDiscover = OT_JOINER_STATE_DISCOVER, 71 kStateConnect = OT_JOINER_STATE_CONNECT, 72 kStateConnected = OT_JOINER_STATE_CONNECTED, 73 kStateEntrust = OT_JOINER_STATE_ENTRUST, 74 kStateJoined = OT_JOINER_STATE_JOINED, 75 }; 76 77 /** 78 * This constructor initializes the Joiner object. 79 * 80 * @param[in] aInstance A reference to the OpenThread instance. 81 * 82 */ 83 explicit Joiner(Instance &aInstance); 84 85 /** 86 * This method starts the Joiner service. 87 * 88 * @param[in] aPskd A pointer to the PSKd. 89 * @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be nullptr). 90 * @param[in] aVendorName A pointer to the Vendor Name (may be nullptr). 91 * @param[in] aVendorModel A pointer to the Vendor Model (may be nullptr). 92 * @param[in] aVendorSwVersion A pointer to the Vendor SW Version (may be nullptr). 93 * @param[in] aVendorData A pointer to the Vendor Data (may be nullptr). 94 * @param[in] aCallback A pointer to a function that is called when the join operation completes. 95 * @param[in] aContext A pointer to application-specific context. 96 * 97 * @retval kErrorNone Successfully started the Joiner service. 98 * @retval kErrorBusy The previous attempt is still on-going. 99 * @retval kErrorInvalidState The IPv6 stack is not enabled or Thread stack is fully enabled. 100 * 101 */ 102 Error Start(const char * aPskd, 103 const char * aProvisioningUrl, 104 const char * aVendorName, 105 const char * aVendorModel, 106 const char * aVendorSwVersion, 107 const char * aVendorData, 108 otJoinerCallback aCallback, 109 void * aContext); 110 111 /** 112 * This method stops the Joiner service. 113 * 114 */ 115 void Stop(void); 116 117 /** 118 * This method gets the Joiner State. 119 * 120 * @returns The Joiner state (see `State`). 121 * 122 */ GetState(void) const123 State GetState(void) const { return mState; } 124 125 /** 126 * This method retrieves the Joiner ID. 127 * 128 * @returns The Joiner ID. 129 * 130 */ GetId(void) const131 const Mac::ExtAddress &GetId(void) const { return mId; } 132 133 /** 134 * This method gets the Jointer Discerner. 135 * 136 * @returns A pointer to the current Joiner Discerner or `nullptr` if none is set. 137 * 138 */ 139 const JoinerDiscerner *GetDiscerner(void) const; 140 141 /** 142 * This method sets the Joiner Discerner. 143 * 144 * The Joiner Discerner is used to calculate the Joiner ID used during commissioning/joining process. 145 * 146 * By default (when a discerner is not provided or cleared), Joiner ID is derived as first 64 bits of the 147 * result of computing SHA-256 over factory-assigned IEEE EUI-64. Note that this is the main behavior expected by 148 * Thread specification. 149 * 150 * @param[in] aDiscerner A Joiner Discerner 151 * 152 * @retval kErrorNone The Joiner Discerner updated successfully. 153 * @retval kErrorInvalidArgs @p aDiscerner is not valid (specified length is not within valid range). 154 * @retval kErrorInvalidState There is an ongoing Joining process so Joiner Discerner could not be changed. 155 * 156 */ 157 Error SetDiscerner(const JoinerDiscerner &aDiscerner); 158 159 /** 160 * This method clears any previously set Joiner Discerner. 161 * 162 * When cleared, Joiner ID is derived as first 64 bits of SHA-256 of factory-assigned IEEE EUI-64. 163 * 164 * @retval kErrorNone The Joiner Discerner cleared and Joiner ID updated. 165 * @retval kErrorInvalidState There is an ongoing Joining process so Joiner Discerner could not be changed. 166 * 167 */ 168 Error ClearDiscerner(void); 169 170 private: 171 static constexpr uint16_t kJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT; 172 173 static constexpr uint32_t kConfigExtAddressDelay = 100; // in msec. 174 static constexpr uint32_t kReponseTimeout = 4000; ///< Max wait time to receive response (in msec). 175 176 struct JoinerRouter 177 { 178 Mac::ExtAddress mExtAddr; 179 Mac::PanId mPanId; 180 uint16_t mJoinerUdpPort; 181 uint8_t mChannel; 182 uint8_t mPriority; 183 }; 184 185 static void HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult, void *aContext); 186 void HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult); 187 188 static void HandleSecureCoapClientConnect(bool aConnected, void *aContext); 189 void HandleSecureCoapClientConnect(bool aConnected); 190 191 static void HandleJoinerFinalizeResponse(void * aContext, 192 otMessage * aMessage, 193 const otMessageInfo *aMessageInfo, 194 Error aResult); 195 void HandleJoinerFinalizeResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult); 196 197 static void HandleJoinerEntrust(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); 198 void HandleJoinerEntrust(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 199 200 static void HandleTimer(Timer &aTimer); 201 void HandleTimer(void); 202 203 static const char *StateToString(State aState); 204 205 void SetState(State aState); 206 void SetIdFromIeeeEui64(void); 207 void SaveDiscoveredJoinerRouter(const Mle::DiscoverScanner::ScanResult &aResult); 208 void TryNextJoinerRouter(Error aPrevError); 209 Error Connect(JoinerRouter &aRouter); 210 void Finish(Error aError); 211 uint8_t CalculatePriority(int8_t aRssi, bool aSteeringDataAllowsAny); 212 213 Error PrepareJoinerFinalizeMessage(const char *aProvisioningUrl, 214 const char *aVendorName, 215 const char *aVendorModel, 216 const char *aVendorSwVersion, 217 const char *aVendorData); 218 void FreeJoinerFinalizeMessage(void); 219 void SendJoinerFinalize(void); 220 void SendJoinerEntrustResponse(const Coap::Message &aRequest, const Ip6::MessageInfo &aRequestInfo); 221 222 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 223 void LogCertMessage(const char *aText, const Coap::Message &aMessage) const; 224 #endif 225 226 Mac::ExtAddress mId; 227 JoinerDiscerner mDiscerner; 228 229 State mState; 230 231 otJoinerCallback mCallback; 232 void * mContext; 233 234 JoinerRouter mJoinerRouters[OPENTHREAD_CONFIG_JOINER_MAX_CANDIDATES]; 235 uint16_t mJoinerRouterIndex; 236 237 Coap::Message *mFinalizeMessage; 238 239 TimerMilli mTimer; 240 Coap::Resource mJoinerEntrust; 241 }; 242 243 } // namespace MeshCoP 244 } // namespace ot 245 246 #endif // OPENTHREAD_CONFIG_JOINER_ENABLE 247 248 #endif // JOINER_HPP_ 249