Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / OpenThread / OpenThreadUtils.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2019 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *          Utility functions for working with OpenThread.
23  */
24
25 #include "OpenThreadUtils.h"
26
27 #include <lib/core/CHIPEncoding.h>
28 #include <lib/support/ErrorStr.h>
29 #include <lib/support/logging/CHIPLogging.h>
30 #include <platform/internal/CHIPDeviceLayerInternal.h>
31
32 #include <openthread/error.h>
33
34 #include <cstdio>
35
36 namespace chip {
37 namespace DeviceLayer {
38 namespace Internal {
39
40 /**
41  * Map an OpenThread error into the OpenChip error space.
42  */
43 CHIP_ERROR MapOpenThreadError(otError otErr)
44 {
45     return (otErr == OT_ERROR_NONE) ? CHIP_NO_ERROR : CHIP_CONFIG_OPENTHREAD_ERROR_MIN + (CHIP_ERROR) otErr;
46 }
47
48 /**
49  * Given an OpenChip error value that represents an OpenThread error, returns a
50  * human-readable NULL-terminated C string describing the error.
51  *
52  * @param[in] buf                   Buffer into which the error string will be placed.
53  * @param[in] bufSize               Size of the supplied buffer in bytes.
54  * @param[in] err                   The error to be described.
55  *
56  * @return true                     If a description string was written into the supplied buffer.
57  * @return false                    If the supplied error was not an OpenThread error.
58  *
59  */
60 bool FormatOpenThreadError(char * buf, uint16_t bufSize, int32_t err)
61 {
62     if (err < CHIP_CONFIG_OPENTHREAD_ERROR_MIN || err > CHIP_CONFIG_OPENTHREAD_ERROR_MAX)
63     {
64         return false;
65     }
66
67 #if CHIP_CONFIG_SHORT_ERROR_STR
68     const char * desc = NULL;
69 #else  // CHIP_CONFIG_SHORT_ERROR_STR
70     otError otErr     = (otError)(err - CHIP_CONFIG_OPENTHREAD_ERROR_MIN);
71     const char * desc = otThreadErrorToString(otErr);
72 #endif // CHIP_CONFIG_SHORT_ERROR_STR
73
74     chip::FormatError(buf, bufSize, "OpenThread", err, desc);
75
76     return true;
77 }
78
79 /**
80  * Register a text error formatter for OpenThread errors.
81  */
82 void RegisterOpenThreadErrorFormatter(void)
83 {
84     static ErrorFormatter sOpenThreadErrorFormatter = { FormatOpenThreadError, NULL };
85
86     RegisterErrorFormatter(&sOpenThreadErrorFormatter);
87 }
88
89 /**
90  * Log information related to a state change in the OpenThread stack.
91  *
92  * NB: This function *must* be called with the Thread stack lock held.
93  */
94 void LogOpenThreadStateChange(otInstance * otInst, uint32_t flags)
95 {
96 #if CHIP_DETAIL_LOGGING
97
98     const uint32_t kParamsChanged = (OT_CHANGED_THREAD_NETWORK_NAME | OT_CHANGED_THREAD_PANID | OT_CHANGED_THREAD_EXT_PANID |
99                                      OT_CHANGED_THREAD_CHANNEL | OT_CHANGED_MASTER_KEY | OT_CHANGED_PSKC);
100
101     static char strBuf[64];
102
103     ChipLogDetail(DeviceLayer, "OpenThread State Changed (Flags: 0x%08x)", flags);
104     if ((flags & OT_CHANGED_THREAD_ROLE) != 0)
105     {
106         ChipLogDetail(DeviceLayer, "   Device Role: %s", OpenThreadRoleToStr(otThreadGetDeviceRole(otInst)));
107     }
108     if ((flags & kParamsChanged) != 0)
109     {
110         ChipLogDetail(DeviceLayer, "   Network Name: %s", otThreadGetNetworkName(otInst));
111         ChipLogDetail(DeviceLayer, "   PAN Id: 0x%04X", otLinkGetPanId(otInst));
112         {
113             const otExtendedPanId * exPanId = otThreadGetExtendedPanId(otInst);
114             snprintf(strBuf, sizeof(strBuf), "0x%02X%02X%02X%02X%02X%02X%02X%02X", exPanId->m8[0], exPanId->m8[1], exPanId->m8[2],
115                      exPanId->m8[3], exPanId->m8[4], exPanId->m8[5], exPanId->m8[6], exPanId->m8[7]);
116             ChipLogDetail(DeviceLayer, "   Extended PAN Id: %s", strBuf);
117         }
118         ChipLogDetail(DeviceLayer, "   Channel: %d", otLinkGetChannel(otInst));
119         {
120             const otMeshLocalPrefix * otMeshPrefix = otThreadGetMeshLocalPrefix(otInst);
121             chip::Inet::IPAddress meshPrefix;
122             memset(meshPrefix.Addr, 0, sizeof(meshPrefix.Addr));
123             memcpy(meshPrefix.Addr, otMeshPrefix->m8, sizeof(otMeshPrefix->m8));
124             meshPrefix.ToString(strBuf);
125             ChipLogDetail(DeviceLayer, "   Mesh Prefix: %s/64", strBuf);
126         }
127 #if CHIP_CONFIG_SECURITY_TEST_MODE
128         {
129             const otMasterKey * otKey = otThreadGetMasterKey(otInst);
130             for (int i = 0; i < OT_MASTER_KEY_SIZE; i++)
131                 snprintf(&strBuf[i * 2], 3, "%02X", otKey->m8[i]);
132             ChipLogDetail(DeviceLayer, "   Master Key: %s", strBuf);
133         }
134 #endif // CHIP_CONFIG_SECURITY_TEST_MODE
135     }
136     if ((flags & OT_CHANGED_THREAD_PARTITION_ID) != 0)
137     {
138         ChipLogDetail(DeviceLayer, "   Partition Id: 0x%" PRIX32, otThreadGetPartitionId(otInst));
139     }
140     if ((flags & (OT_CHANGED_IP6_ADDRESS_ADDED | OT_CHANGED_IP6_ADDRESS_REMOVED)) != 0)
141     {
142         ChipLogDetail(DeviceLayer, "   Thread Unicast Addresses:");
143         for (const otNetifAddress * addr = otIp6GetUnicastAddresses(otInst); addr != NULL; addr = addr->mNext)
144         {
145             chip::Inet::IPAddress ipAddr;
146             memcpy(ipAddr.Addr, addr->mAddress.mFields.m32, sizeof(ipAddr.Addr));
147
148             ipAddr.ToString(strBuf);
149
150             ChipLogDetail(DeviceLayer, "        %s/%d%s%s%s", strBuf, addr->mPrefixLength, addr->mValid ? " valid" : "",
151                           addr->mPreferred ? " preferred" : "", addr->mRloc ? " rloc" : "");
152         }
153     }
154
155 #endif // CHIP_DETAIL_LOGGING
156 }
157
158 void LogOpenThreadPacket(const char * titleStr, otMessage * pkt)
159 {
160 #if CHIP_DETAIL_LOGGING
161
162     char srcStr[50], destStr[50], typeBuf[20];
163     const char * type = typeBuf;
164     IPAddress addr;
165     uint8_t headerData[44];
166     uint16_t pktLen;
167
168     const uint8_t & IPv6_NextHeader     = headerData[6];
169     const uint8_t * const IPv6_SrcAddr  = headerData + 8;
170     const uint8_t * const IPv6_DestAddr = headerData + 24;
171     const uint8_t * const IPv6_SrcPort  = headerData + 40;
172     const uint8_t * const IPv6_DestPort = headerData + 42;
173     const uint8_t & ICMPv6_Type         = headerData[40];
174     const uint8_t & ICMPv6_Code         = headerData[41];
175
176     constexpr uint8_t kIPProto_UDP    = 17;
177     constexpr uint8_t kIPProto_TCP    = 6;
178     constexpr uint8_t kIPProto_ICMPv6 = 58;
179
180     constexpr uint8_t kICMPType_EchoRequest  = 128;
181     constexpr uint8_t kICMPType_EchoResponse = 129;
182
183     pktLen = otMessageGetLength(pkt);
184
185     if (pktLen >= sizeof(headerData))
186     {
187         otMessageRead(pkt, 0, headerData, sizeof(headerData));
188
189         memcpy(addr.Addr, IPv6_SrcAddr, 16);
190         addr.ToString(srcStr);
191
192         memcpy(addr.Addr, IPv6_DestAddr, 16);
193         addr.ToString(destStr);
194
195         if (IPv6_NextHeader == kIPProto_UDP)
196         {
197             type = "UDP";
198         }
199         else if (IPv6_NextHeader == kIPProto_TCP)
200         {
201             type = "TCP";
202         }
203         else if (IPv6_NextHeader == kIPProto_ICMPv6)
204         {
205             if (ICMPv6_Type == kICMPType_EchoRequest)
206             {
207                 type = "ICMPv6 Echo Request";
208             }
209             else if (ICMPv6_Type == kICMPType_EchoResponse)
210             {
211                 type = "ICMPv6 Echo Response";
212             }
213             else
214             {
215                 snprintf(typeBuf, sizeof(typeBuf), "ICMPv6 %" PRIu8 ",%" PRIu8, ICMPv6_Type, ICMPv6_Code);
216             }
217         }
218         else
219         {
220             snprintf(typeBuf, sizeof(typeBuf), "IP proto %" PRIu8, IPv6_NextHeader);
221         }
222
223         if (IPv6_NextHeader == kIPProto_UDP || IPv6_NextHeader == kIPProto_TCP)
224         {
225             snprintf(srcStr + strlen(srcStr), 13, ", port %" PRIu16, Encoding::BigEndian::Get16(IPv6_SrcPort));
226             snprintf(destStr + strlen(destStr), 13, ", port %" PRIu16, Encoding::BigEndian::Get16(IPv6_DestPort));
227         }
228
229         ChipLogDetail(DeviceLayer, "%s: %s, len %" PRIu16, titleStr, type, pktLen);
230         ChipLogDetail(DeviceLayer, "    src  %s", srcStr);
231         ChipLogDetail(DeviceLayer, "    dest %s", destStr);
232     }
233     else
234     {
235         ChipLogDetail(DeviceLayer, "%s: %s, len %" PRIu16, titleStr, "(decode error)", pktLen);
236     }
237
238 #endif // CHIP_DETAIL_LOGGING
239 }
240
241 bool IsOpenThreadMeshLocalAddress(otInstance * otInst, const IPAddress & addr)
242 {
243     const otMeshLocalPrefix * otMeshPrefix = otThreadGetMeshLocalPrefix(otInst);
244
245     return otMeshPrefix != NULL && memcmp(otMeshPrefix->m8, addr.Addr, OT_MESH_LOCAL_PREFIX_SIZE) == 0;
246 }
247
248 const char * OpenThreadRoleToStr(otDeviceRole role)
249 {
250     switch (role)
251     {
252     case OT_DEVICE_ROLE_DISABLED:
253         return "DISABLED";
254     case OT_DEVICE_ROLE_DETACHED:
255         return "DETACHED";
256     case OT_DEVICE_ROLE_CHILD:
257         return "CHILD";
258     case OT_DEVICE_ROLE_ROUTER:
259         return "ROUTER";
260     case OT_DEVICE_ROLE_LEADER:
261         return "LEADER";
262     default:
263         return "(unknown)";
264     }
265 }
266
267 } // namespace Internal
268 } // namespace DeviceLayer
269 } // namespace chip