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 handle network diagnostic. 32 */ 33 34 #ifndef NETWORK_DIAGNOSTIC_HPP_ 35 #define NETWORK_DIAGNOSTIC_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <openthread/netdiag.h> 40 41 #include "common/callback.hpp" 42 #include "common/locator.hpp" 43 #include "common/non_copyable.hpp" 44 #include "net/udp6.hpp" 45 #include "thread/network_diagnostic_tlvs.hpp" 46 #include "thread/tmf.hpp" 47 #include "thread/uri_paths.hpp" 48 49 namespace ot { 50 51 namespace Utils { 52 class MeshDiag; 53 } 54 55 namespace NetworkDiagnostic { 56 57 /** 58 * @addtogroup core-netdiag 59 * 60 * @brief 61 * This module includes definitions for sending and handling Network Diagnostic Commands. 62 * 63 * @{ 64 */ 65 66 class Client; 67 68 /** 69 * Implements the Network Diagnostic server responding to requests. 70 * 71 */ 72 class Server : public InstanceLocator, private NonCopyable 73 { 74 friend class Tmf::Agent; 75 friend class Client; 76 77 public: 78 /** 79 * Initializes the Server. 80 * 81 * @param[in] aInstance The OpenThread instance. 82 * 83 */ 84 explicit Server(Instance &aInstance); 85 86 #if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE 87 /** 88 * Returns the vendor name string. 89 * 90 * @returns The vendor name string. 91 * 92 */ GetVendorName(void) const93 const char *GetVendorName(void) const { return mVendorName; } 94 95 /** 96 * Sets the vendor name string. 97 * 98 * @param[in] aVendorName The vendor name string. 99 * 100 * @retval kErrorNone Successfully set the vendor name. 101 * @retval kErrorInvalidArgs @p aVendorName is not valid (too long or not UTF8). 102 * 103 */ 104 Error SetVendorName(const char *aVendorName); 105 106 /** 107 * Returns the vendor model string. 108 * 109 * @returns The vendor model string. 110 * 111 */ GetVendorModel(void) const112 const char *GetVendorModel(void) const { return mVendorModel; } 113 114 /** 115 * Sets the vendor model string. 116 * 117 * @param[in] aVendorModel The vendor model string. 118 * 119 * @retval kErrorNone Successfully set the vendor model. 120 * @retval kErrorInvalidArgs @p aVendorModel is not valid (too long or not UTF8). 121 * 122 */ 123 Error SetVendorModel(const char *aVendorModel); 124 125 /** 126 * Returns the vendor software version string. 127 * 128 * @returns The vendor software version string. 129 * 130 */ GetVendorSwVersion(void) const131 const char *GetVendorSwVersion(void) const { return mVendorSwVersion; } 132 133 /** 134 * Sets the vendor sw version string 135 * 136 * @param[in] aVendorSwVersion The vendor sw version string. 137 * 138 * @retval kErrorNone Successfully set the vendor sw version. 139 * @retval kErrorInvalidArgs @p aVendorSwVersion is not valid (too long or not UTF8). 140 * 141 */ 142 Error SetVendorSwVersion(const char *aVendorSwVersion); 143 144 /** 145 * Returns the vendor app URL string. 146 * 147 * @returns the vendor app URL string. 148 * 149 */ GetVendorAppUrl(void) const150 const char *GetVendorAppUrl(void) const { return mVendorAppUrl; } 151 152 /** 153 * Sets the vendor app URL string. 154 * 155 * @param[in] aVendorAppUrl The vendor app URL string 156 * 157 * @retval kErrorNone Successfully set the vendor app URL. 158 * @retval kErrorInvalidArgs @p aVendorAppUrl is not valid (too long or not UTF8). 159 * 160 */ 161 Error SetVendorAppUrl(const char *aVendorAppUrl); 162 163 #else GetVendorName(void) const164 const char *GetVendorName(void) const { return kVendorName; } GetVendorModel(void) const165 const char *GetVendorModel(void) const { return kVendorModel; } GetVendorSwVersion(void) const166 const char *GetVendorSwVersion(void) const { return kVendorSwVersion; } GetVendorAppUrl(void) const167 const char *GetVendorAppUrl(void) const { return kVendorAppUrl; } 168 #endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE 169 170 private: 171 static constexpr uint16_t kMaxChildEntries = 398; 172 static constexpr uint16_t kAnswerMessageLengthThreshold = 800; 173 174 #if OPENTHREAD_FTD 175 struct AnswerInfo 176 { AnswerInfoot::NetworkDiagnostic::Server::AnswerInfo177 AnswerInfo(void) 178 : mAnswerIndex(0) 179 , mQueryId(0) 180 , mHasQueryId(false) 181 , mFirstAnswer(nullptr) 182 { 183 } 184 185 uint16_t mAnswerIndex; 186 uint16_t mQueryId; 187 bool mHasQueryId; 188 Message::Priority mPriority; 189 Coap::Message *mFirstAnswer; 190 }; 191 #endif 192 193 static const char kVendorName[]; 194 static const char kVendorModel[]; 195 static const char kVendorSwVersion[]; 196 static const char kVendorAppUrl[]; 197 198 Error AppendDiagTlv(uint8_t aTlvType, Message &aMessage); 199 Error AppendIp6AddressList(Message &aMessage); 200 Error AppendMacCounters(Message &aMessage); 201 Error AppendRequestedTlvs(const Message &aRequest, Message &aResponse); 202 void PrepareMessageInfoForDest(const Ip6::Address &aDestination, Tmf::MessageInfo &aMessageInfo) const; 203 204 #if OPENTHREAD_MTD 205 void SendAnswer(const Ip6::Address &aDestination, const Message &aRequest); 206 #elif OPENTHREAD_FTD 207 Error AllocateAnswer(Coap::Message *&aAnswer, AnswerInfo &aInfo); 208 Error CheckAnswerLength(Coap::Message *&aAnswer, AnswerInfo &aInfo); 209 bool IsLastAnswer(const Coap::Message &aAnswer) const; 210 void FreeAllRelatedAnswers(Coap::Message &aFirstAnswer); 211 void PrepareAndSendAnswers(const Ip6::Address &aDestination, const Message &aRequest); 212 void SendNextAnswer(Coap::Message &aAnswer, const Ip6::Address &aDestination); 213 Error AppendChildTable(Message &aMessage); 214 Error AppendChildTableAsChildTlvs(Coap::Message *&aAnswer, AnswerInfo &aInfo); 215 Error AppendRouterNeighborTlvs(Coap::Message *&aAnswer, AnswerInfo &aInfo); 216 Error AppendChildTableIp6AddressList(Coap::Message *&aAnswer, AnswerInfo &aInfo); 217 Error AppendChildIp6AddressListTlv(Coap::Message &aAnswer, const Child &aChild); 218 219 static void HandleAnswerResponse(void *aContext, 220 otMessage *aMessage, 221 const otMessageInfo *aMessageInfo, 222 Error aResult); 223 void HandleAnswerResponse(Coap::Message &aNextAnswer, 224 Coap::Message *aResponse, 225 const Ip6::MessageInfo *aMessageInfo, 226 Error aResult); 227 #endif 228 229 template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 230 231 #if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE 232 VendorNameTlv::StringType mVendorName; 233 VendorModelTlv::StringType mVendorModel; 234 VendorSwVersionTlv::StringType mVendorSwVersion; 235 VendorAppUrlTlv::StringType mVendorAppUrl; 236 #endif 237 238 #if OPENTHREAD_FTD 239 Coap::MessageQueue mAnswerQueue; 240 #endif 241 }; 242 243 DeclareTmfHandler(Server, kUriDiagnosticGetRequest); 244 DeclareTmfHandler(Server, kUriDiagnosticGetQuery); 245 DeclareTmfHandler(Server, kUriDiagnosticGetAnswer); 246 247 #if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE 248 249 /** 250 * Implements the Network Diagnostic client sending requests and queries. 251 * 252 */ 253 class Client : public InstanceLocator, private NonCopyable 254 { 255 friend class Tmf::Agent; 256 friend class Utils::MeshDiag; 257 258 public: 259 typedef otNetworkDiagIterator Iterator; ///< Iterator to go through TLVs in `GetNextDiagTlv()`. 260 typedef otNetworkDiagTlv TlvInfo; ///< Parse info from a Network Diagnostic TLV. 261 typedef otNetworkDiagChildEntry ChildInfo; ///< Parsed info for child table entry. 262 typedef otReceiveDiagnosticGetCallback GetCallback; ///< Diagnostic Get callback function pointer type. 263 264 static constexpr Iterator kIteratorInit = OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT; ///< Initializer for Iterator. 265 266 /** 267 * Initializes the Client. 268 * 269 * @param[in] aInstance The OpenThread instance. 270 * 271 */ 272 explicit Client(Instance &aInstance); 273 274 /** 275 * Sends Diagnostic Get request. If the @p aDestination is of multicast type, the DIAG_GET.qry 276 * message is sent or the DIAG_GET.req otherwise. 277 * 278 * @param[in] aDestination The destination address. 279 * @param[in] aTlvTypes An array of Network Diagnostic TLV types. 280 * @param[in] aCount Number of types in @p aTlvTypes. 281 * @param[in] aCallback Callback when Network Diagnostic Get response is received (can be NULL). 282 * @param[in] Context Application-specific context used with @p aCallback. 283 * 284 */ 285 Error SendDiagnosticGet(const Ip6::Address &aDestination, 286 const uint8_t aTlvTypes[], 287 uint8_t aCount, 288 GetCallback aCallback, 289 void *Context); 290 291 /** 292 * Sends Diagnostic Reset request. 293 * 294 * @param[in] aDestination The destination address. 295 * @param[in] aTlvTypes An array of Network Diagnostic TLV types. 296 * @param[in] aCount Number of types in aTlvTypes 297 * 298 */ 299 Error SendDiagnosticReset(const Ip6::Address &aDestination, const uint8_t aTlvTypes[], uint8_t aCount); 300 301 /** 302 * Gets the next Network Diagnostic TLV in a given message. 303 * 304 * @param[in] aMessage Message to read TLVs from. 305 * @param[in,out] aIterator The Network Diagnostic iterator. To get the first TLV set it to `kIteratorInit`. 306 * @param[out] aTlvInfo A reference to a `TlvInfo` to output the next TLV data. 307 * 308 * @retval kErrorNone Successfully found the next Network Diagnostic TLV. 309 * @retval kErrorNotFound No subsequent Network Diagnostic TLV exists in the message. 310 * @retval kErrorParse Parsing the next Network Diagnostic failed. 311 * 312 */ 313 static Error GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, TlvInfo &aTlvInfo); 314 315 /** 316 * This method returns the query ID used for the last Network Diagnostic Query command. 317 * 318 * @returns The query ID used for last query. 319 * 320 */ GetLastQueryId(void) const321 uint16_t GetLastQueryId(void) const { return mQueryId; } 322 323 private: 324 Error SendCommand(Uri aUri, 325 Message::Priority aPriority, 326 const Ip6::Address &aDestination, 327 const uint8_t aTlvTypes[], 328 uint8_t aCount, 329 Coap::ResponseHandler aHandler = nullptr, 330 void *aContext = nullptr); 331 332 static void HandleGetResponse(void *aContext, 333 otMessage *aMessage, 334 const otMessageInfo *aMessageInfo, 335 Error aResult); 336 void HandleGetResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult); 337 338 template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 339 340 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) 341 static const char *UriToString(Uri aUri); 342 #endif 343 344 uint16_t mQueryId; 345 Callback<GetCallback> mGetCallback; 346 }; 347 348 DeclareTmfHandler(Client, kUriDiagnosticReset); 349 350 #endif // OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE 351 352 /** 353 * @} 354 */ 355 } // namespace NetworkDiagnostic 356 357 } // namespace ot 358 359 #endif // NETWORK_DIAGNOSTIC_HPP_ 360