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