Change script for apply upstream code
[platform/upstream/connectedhomeip.git] / src / inet / tests / TestInetCommon.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2013-2018 Nest Labs, Inc.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *      This file implements constants, globals and interfaces common to
22  *      and used by all CHP Inet layer library test applications and
23  *      tools.
24  *
25  *      NOTE: These do not comprise a public part of the CHIP API and
26  *            are subject to change without notice.
27  *
28  */
29
30 #ifndef __STDC_LIMIT_MACROS
31 #define __STDC_LIMIT_MACROS
32 #endif
33 #ifndef __STDC_FORMAT_MACROS
34 #define __STDC_FORMAT_MACROS
35 #endif
36
37 #include "TestInetCommon.h"
38
39 #include <vector>
40
41 #include <inttypes.h>
42 #include <signal.h>
43 #include <stdint.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #include <unistd.h>
47
48 #include <inet/InetFaultInjection.h>
49 #include <support/CHIPFaultInjection.h>
50 #include <support/CHIPMem.h>
51 #include <support/ScopedBuffer.h>
52 #include <system/SystemFaultInjection.h>
53 #include <system/SystemTimer.h>
54
55 #if CHIP_SYSTEM_CONFIG_USE_LWIP
56 #include <lwip/dns.h>
57 #include <lwip/init.h>
58 #include <lwip/netif.h>
59 #include <lwip/sys.h>
60 #include <lwip/tcpip.h>
61 #include <netif/etharp.h>
62
63 #if CHIP_TARGET_STYLE_UNIX
64
65 // TapAddrAutoconf and TapInterface are only needed for LwIP on
66 // sockets simulation in which a host tap/tun interface is used to
67 // proxy the LwIP stack onto a host native network interface.
68
69 #include "TapAddrAutoconf.h"
70 #include "TapInterface.h"
71 #endif // CHIP_TARGET_STYLE_UNIX
72 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
73
74 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
75 #include <arpa/inet.h>
76 #include <sys/select.h>
77 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
78
79 using namespace chip;
80 using namespace chip::Inet;
81
82 #if CHIP_SYSTEM_CONFIG_USE_LWIP
83 static sys_mbox_t * sLwIPEventQueue   = NULL;
84 static unsigned int sLwIPAcquireCount = 0;
85
86 static void AcquireLwIP(void)
87 {
88     if (sLwIPAcquireCount++ == 0)
89     {
90         sys_mbox_new(sLwIPEventQueue, 100);
91     }
92 }
93
94 static void ReleaseLwIP(void)
95 {
96 #if !(LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1)
97     if (sLwIPAcquireCount > 0 && --sLwIPAcquireCount == 0)
98     {
99         tcpip_finish(NULL, NULL);
100     }
101 #endif
102 }
103 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
104
105 struct RestartCallbackContext
106 {
107     int mArgc;
108     char ** mArgv;
109 };
110
111 static void RebootCallbackFn();
112 static void PostInjectionCallbackFn(nl::FaultInjection::Manager * aManager, nl::FaultInjection::Identifier aId,
113                                     nl::FaultInjection::Record * aFaultRecord);
114
115 static struct RestartCallbackContext sRestartCallbackCtx;
116 static nl::FaultInjection::Callback sFuzzECHeaderCb;
117 static nl::FaultInjection::Callback sAsyncEventCb;
118
119 // clang-format off
120 static nl::FaultInjection::GlobalContext sFaultInjectionGlobalContext = {
121     {
122         RebootCallbackFn,
123         PostInjectionCallbackFn
124     }
125 };
126 // clang-format on
127
128 System::Layer gSystemLayer;
129
130 Inet::InetLayer gInet;
131
132 #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
133 #if CHIP_TARGET_STYLE_UNIX
134 // TapAddrAutoconf and TapInterface are only needed for LwIP on
135 // sockets simulation in which a host tap/tun interface is used to
136 // proxy the LwIP stack onto a host native network interface.
137 // CollectTapAddresses() is only available on such targets.
138
139 static std::vector<TapInterface> sTapIFs;
140 #endif                                    // CHIP_TARGET_STYLE_UNIX
141 static std::vector<struct netif> sNetIFs; // interface to filter
142 #endif                                    // CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
143
144 #if CHIP_SYSTEM_CONFIG_USE_LWIP
145
146 static bool NetworkIsReady();
147 static void OnLwIPInitComplete(void * arg);
148 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
149
150 char gDefaultTapDeviceName[32];
151 bool gDone            = false;
152 bool gSigusr1Received = false;
153
154 static void UseStdoutLineBuffering()
155 {
156     // Set stdout to be line buffered with a buffer of 512 (will flush on new line
157     // or when the buffer of 512 is exceeded).
158 #if CHIP_CONFIG_MEMORY_MGMT_MALLOC
159     constexpr char * buf = nullptr;
160 #else
161     static char buf[512];
162 #endif // CHIP_CONFIG_MEMORY_MGMT_MALLOC
163     setvbuf(stdout, buf, _IOLBF, 512);
164 }
165
166 void InitTestInetCommon()
167 {
168     chip::Platform::MemoryInit();
169     UseStdoutLineBuffering();
170 }
171
172 static void ExitOnSIGUSR1Handler(int signum)
173 {
174     // exit() allows us a slightly better clean up (gcov data) than SIGINT's exit
175     exit(0);
176 }
177
178 // We set a hook to exit when we receive SIGUSR1, SIGTERM or SIGHUP
179 void SetSIGUSR1Handler()
180 {
181     SetSignalHandler(ExitOnSIGUSR1Handler);
182 }
183
184 void SetSignalHandler(SignalHandler handler)
185 {
186     struct sigaction sa;
187     int signals[] = { SIGUSR1 };
188     size_t i;
189
190     memset(&sa, 0, sizeof(sa));
191     sa.sa_handler = handler;
192
193     for (i = 0; i < sizeof(signals) / sizeof(signals[0]); i++)
194     {
195         if (sigaction(signals[i], &sa, nullptr) == -1)
196         {
197             perror("Can't catch signal");
198             exit(1);
199         }
200     }
201 }
202
203 void InitSystemLayer()
204 {
205 #if CHIP_SYSTEM_CONFIG_USE_LWIP
206     AcquireLwIP();
207
208     gSystemLayer.Init(sLwIPEventQueue);
209 #else  // !CHIP_SYSTEM_CONFIG_USE_LWIP
210     gSystemLayer.Init(nullptr);
211 #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
212 }
213
214 void ShutdownSystemLayer()
215 {
216     gSystemLayer.Shutdown();
217
218 #if CHIP_SYSTEM_CONFIG_USE_LWIP
219     ReleaseLwIP();
220 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
221 }
222
223 #if CHIP_SYSTEM_CONFIG_USE_LWIP
224 static void PrintNetworkState()
225 {
226     char intfName[10];
227
228     for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
229     {
230         struct netif * netIF = &(sNetIFs[j]);
231 #if CHIP_TARGET_STYLE_UNIX
232         // TapAddrAutoconf and TapInterface are only needed for LwIP on
233         // sockets simulation in which a host tap/tun interface is used to
234         // proxy the LwIP stack onto a host native network interface.
235         // CollectTapAddresses() is only available on such targets.
236
237         TapInterface * tapIF = &(sTapIFs[j]);
238 #endif // CHIP_TARGET_STYLE_UNIX
239         GetInterfaceName(netIF, intfName, sizeof(intfName));
240
241         printf("LwIP interface ready\n");
242         printf("  Interface Name: %s\n", intfName);
243         printf("  Tap Device: %s\n", gNetworkOptions.TapDeviceName[j]);
244 #if CHIP_TARGET_STYLE_UNIX
245         // TapAddrAutoconf and TapInterface are only needed for LwIP on
246         // sockets simulation in which a host tap/tun interface is used to
247         // proxy the LwIP stack onto a host native network interface.
248         // CollectTapAddresses() is only available on such targets.
249
250         printf("  MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", tapIF->macAddr[0], tapIF->macAddr[1], tapIF->macAddr[2],
251                tapIF->macAddr[3], tapIF->macAddr[4], tapIF->macAddr[5]);
252 #endif // CHIP_TARGET_STYLE_UNIX
253
254 #if INET_CONFIG_ENABLE_IPV4
255         printf("  IPv4 Address: %s\n", ipaddr_ntoa(&(netIF->ip_addr)));
256         printf("  IPv4 Mask: %s\n", ipaddr_ntoa(&(netIF->netmask)));
257         printf("  IPv4 Gateway: %s\n", ipaddr_ntoa(&(netIF->gw)));
258 #endif // INET_CONFIG_ENABLE_IPV4
259         for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
260         {
261             if (!ip6_addr_isany(netif_ip6_addr(netIF, i)))
262             {
263                 printf("  IPv6 address: %s, 0x%02x\n", ip6addr_ntoa(netif_ip6_addr(netIF, i)), netif_ip6_addr_state(netIF, i));
264             }
265         }
266     }
267 #if INET_CONFIG_ENABLE_DNS_RESOLVER
268     char dnsServerAddrStr[DNS_MAX_NAME_LENGTH];
269     printf("  DNS Server: %s\n", gNetworkOptions.DNSServerAddr.ToString(dnsServerAddrStr, sizeof(dnsServerAddrStr)));
270 #endif // INET_CONFIG_ENABLE_DNS_RESOLVER
271 }
272 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
273
274 void InitNetwork()
275 {
276     void * lContext = nullptr;
277
278 #if CHIP_SYSTEM_CONFIG_USE_LWIP
279 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
280
281     tcpip_init(NULL, NULL);
282
283 #else // !CHIP_SYSTEM_CONFIG_USE_SOCKETS
284
285     // If an tap device name hasn't been specified, derive one from the IPv6 interface id.
286
287     if (gNetworkOptions.TapDeviceName.empty())
288     {
289         for (size_t j = 0; j < gNetworkOptions.LocalIPv6Addr.size(); j++)
290         {
291             uint64_t iid    = gNetworkOptions.LocalIPv6Addr[j].InterfaceId();
292             char * tap_name = (char *) chip::Platform::MemoryAlloc(sizeof(gDefaultTapDeviceName));
293             assert(tap_name);
294             snprintf(tap_name, sizeof(gDefaultTapDeviceName), "chip-dev-%" PRIx64, iid & 0xFFFF);
295             gNetworkOptions.TapDeviceName.push_back(tap_name);
296         }
297     }
298
299 #if CHIP_TARGET_STYLE_UNIX
300     // TapAddrAutoconf and TapInterface are only needed for LwIP on
301     // sockets simulation in which a host tap/tun interface is used to
302     // proxy the LwIP stack onto a host native network interface.
303     // CollectTapAddresses() is only available on such targets.
304
305     sTapIFs.clear();
306 #endif // CHIP_TARGET_STYLE_UNIX
307     sNetIFs.clear();
308
309     for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
310     {
311 #if CHIP_TARGET_STYLE_UNIX
312         // TapAddrAutoconf and TapInterface are only needed for LwIP on
313         // sockets simulation in which a host tap/tun interface is used to
314         // proxy the LwIP stack onto a host native network interface.
315         // CollectTapAddresses() is only available on such targets.
316
317         TapInterface tapIF;
318         sTapIFs.push_back(tapIF);
319 #endif // CHIP_TARGET_STYLE_UNIX
320         struct netif netIF;
321         sNetIFs.push_back(netIF);
322     }
323
324 #if CHIP_TARGET_STYLE_UNIX
325
326     // TapAddrAutoconf and TapInterface are only needed for LwIP on
327     // sockets simulation in which a host tap/tun interface is used to
328     // proxy the LwIP stack onto a host native network interface.
329     // CollectTapAddresses() is only available on such targets.
330
331     err_t lwipErr;
332
333     for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
334     {
335         lwipErr = TapInterface_Init(&(sTapIFs[j]), gNetworkOptions.TapDeviceName[j], NULL);
336         if (lwipErr != ERR_OK)
337         {
338             printf("Failed to initialize tap device %s: %s\n", gNetworkOptions.TapDeviceName[j],
339                    ErrorStr(System::MapErrorLwIP(lwipErr)));
340             exit(EXIT_FAILURE);
341         }
342     }
343 #endif // CHIP_TARGET_STYLE_UNIX
344     tcpip_init(OnLwIPInitComplete, NULL);
345
346     // Lock LwIP stack
347     LOCK_TCPIP_CORE();
348
349     for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
350     {
351         std::vector<char *> addrsVec;
352
353         addrsVec.clear();
354
355 #if CHIP_TARGET_STYLE_UNIX
356
357         // TapAddrAutoconf and TapInterface are only needed for LwIP on
358         // sockets simulation in which a host tap/tun interface is used to
359         // proxy the LwIP stack onto a host native network interface.
360         // CollectTapAddresses() is only available on such targets.
361         if (gNetworkOptions.TapUseSystemConfig)
362         {
363             CollectTapAddresses(addrsVec, gNetworkOptions.TapDeviceName[j]);
364         }
365 #endif // CHIP_TARGET_STYLE_UNIX
366 #if INET_CONFIG_ENABLE_IPV4
367
368         IPAddress ip4Addr = (j < gNetworkOptions.LocalIPv4Addr.size()) ? gNetworkOptions.LocalIPv4Addr[j] : IPAddress::Any;
369         for (size_t n = 0; n < addrsVec.size(); n++)
370         {
371             IPAddress auto_addr;
372             if (IPAddress::FromString(addrsVec[n], auto_addr) && auto_addr.IsIPv4())
373             {
374                 ip4Addr = auto_addr;
375             }
376         }
377
378 #if CHIP_TARGET_STYLE_UNIX
379         // TapAddrAutoconf and TapInterface are only needed for LwIP on
380         // sockets simulation in which a host tap/tun interface is used to
381         // proxy the LwIP stack onto a host native network interface.
382         // CollectTapAddresses() is only available on such targets.
383
384         IPAddress ip4Gateway = (j < gNetworkOptions.IPv4GatewayAddr.size()) ? gNetworkOptions.IPv4GatewayAddr[j] : IPAddress::Any;
385
386         {
387 #if LWIP_VERSION_MAJOR > 1
388             ip4_addr_t ip4AddrLwIP, ip4NetmaskLwIP, ip4GatewayLwIP;
389 #else  // LWIP_VERSION_MAJOR <= 1
390             ip_addr_t ip4AddrLwIP, ip4NetmaskLwIP, ip4GatewayLwIP;
391 #endif // LWIP_VERSION_MAJOR <= 1
392
393             ip4AddrLwIP = ip4Addr.ToIPv4();
394             IP4_ADDR(&ip4NetmaskLwIP, 255, 255, 255, 0);
395             ip4GatewayLwIP = ip4Gateway.ToIPv4();
396             netif_add(&(sNetIFs[j]), &ip4AddrLwIP, &ip4NetmaskLwIP, &ip4GatewayLwIP, &(sTapIFs[j]), TapInterface_SetupNetif,
397                       tcpip_input);
398         }
399 #endif // CHIP_TARGET_STYLE_UNIX
400
401 #endif // INET_CONFIG_ENABLE_IPV4
402
403         netif_create_ip6_linklocal_address(&(sNetIFs[j]), 1);
404
405 #if !(LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1)
406         if (j < gNetworkOptions.LocalIPv6Addr.size())
407         {
408             ip6_addr_t ip6addr = gNetworkOptions.LocalIPv6Addr[j].ToIPv6();
409             s8_t index;
410             netif_add_ip6_address_with_route(&(sNetIFs[j]), &ip6addr, 64, &index);
411             // add ipv6 route for ipv6 address
412             if (j < gNetworkOptions.IPv6GatewayAddr.size())
413             {
414                 static ip6_addr_t br_ip6_addr = gNetworkOptions.IPv6GatewayAddr[j].ToIPv6();
415                 struct ip6_prefix ip6_prefix;
416                 ip6_prefix.addr       = Inet::IPAddress::Any.ToIPv6();
417                 ip6_prefix.prefix_len = 0;
418                 ip6_add_route_entry(&ip6_prefix, &sNetIFs[j], &br_ip6_addr, NULL);
419             }
420             if (index >= 0)
421             {
422                 netif_ip6_addr_set_state(&(sNetIFs[j]), index, IP6_ADDR_PREFERRED);
423             }
424         }
425         for (size_t n = 0; n < addrsVec.size(); n++)
426         {
427             IPAddress auto_addr;
428             if (IPAddress::FromString(addrsVec[n], auto_addr) && !auto_addr.IsIPv4())
429             {
430                 ip6_addr_t ip6addr = auto_addr.ToIPv6();
431                 s8_t index;
432                 if (auto_addr.IsIPv6LinkLocal())
433                     continue; // skip over the LLA addresses, LwIP is aready adding those
434                 if (auto_addr.IsIPv6Multicast())
435                     continue; // skip over the multicast addresses from host for now.
436                 netif_add_ip6_address_with_route(&(sNetIFs[j]), &ip6addr, 64, &index);
437                 if (index >= 0)
438                 {
439                     netif_ip6_addr_set_state(&(sNetIFs[j]), index, IP6_ADDR_PREFERRED);
440                 }
441             }
442         }
443 #endif
444
445         netif_set_up(&(sNetIFs[j]));
446         netif_set_link_up(&(sNetIFs[j]));
447     }
448
449     netif_set_default(&(sNetIFs[0]));
450     // UnLock LwIP stack
451
452     UNLOCK_TCPIP_CORE();
453
454     while (!NetworkIsReady())
455     {
456         struct timeval lSleepTime;
457         lSleepTime.tv_sec  = 0;
458         lSleepTime.tv_usec = 100000;
459         ServiceEvents(lSleepTime);
460     }
461
462     // FIXME: this is kinda nasty :(
463     // Force new IP address to be ready, bypassing duplicate detection.
464
465     for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
466     {
467         if (j < gNetworkOptions.LocalIPv6Addr.size())
468         {
469             netif_ip6_addr_set_state(&(sNetIFs[j]), 2, 0x30);
470         }
471         else
472         {
473             netif_ip6_addr_set_state(&(sNetIFs[j]), 1, 0x30);
474         }
475     }
476
477 #if INET_CONFIG_ENABLE_DNS_RESOLVER
478     if (gNetworkOptions.DNSServerAddr != IPAddress::Any)
479     {
480 #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
481         ip_addr_t dnsServerAddr = gNetworkOptions.DNSServerAddr.ToLwIPAddr();
482 #else // LWIP_VERSION_MAJOR <= 1
483 #if INET_CONFIG_ENABLE_IPV4
484         ip_addr_t dnsServerAddr = gNetworkOptions.DNSServerAddr.ToIPv4();
485 #else // !INET_CONFIG_ENABLE_IPV4
486 #error "No support for DNS Resolver without IPv4!"
487 #endif // !INET_CONFIG_ENABLE_IPV4
488 #endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
489
490         dns_setserver(0, &dnsServerAddr);
491     }
492 #endif // INET_CONFIG_ENABLE_DNS_RESOLVER
493
494     PrintNetworkState();
495
496 #endif // !CHIP_SYSTEM_CONFIG_USE_SOCKETS
497
498     AcquireLwIP();
499     lContext = sLwIPEventQueue;
500
501 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
502
503     gInet.Init(gSystemLayer, lContext);
504 }
505
506 void ServiceEvents(struct ::timeval & aSleepTime)
507 {
508     static bool printed = false;
509
510     if (!printed)
511     {
512 #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
513         if (NetworkIsReady())
514 #endif
515         {
516             printf("CHIP node ready to service events; PID: %d; PPID: %d\n", getpid(), getppid());
517             fflush(stdout);
518             printed = true;
519         }
520     }
521 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
522     fd_set readFDs, writeFDs, exceptFDs;
523     int numFDs = 0;
524
525     FD_ZERO(&readFDs);
526     FD_ZERO(&writeFDs);
527     FD_ZERO(&exceptFDs);
528
529 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
530     if (gSystemLayer.State() == System::kLayerState_Initialized)
531         gSystemLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
532 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
533
534 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
535     if (gInet.State == InetLayer::kState_Initialized)
536         gInet.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
537 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
538
539     int selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &aSleepTime);
540     if (selectRes < 0)
541     {
542         printf("select failed: %s\n", ErrorStr(System::MapErrorPOSIX(errno)));
543         return;
544     }
545 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
546
547     if (gSystemLayer.State() == System::kLayerState_Initialized)
548     {
549 #if CHIP_SYSTEM_CONFIG_USE_LWIP
550         static uint32_t sRemainingSystemLayerEventDelay = 0;
551 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
552
553 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
554
555         gSystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
556
557 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
558
559 #if CHIP_SYSTEM_CONFIG_USE_LWIP
560         if (gSystemLayer.State() == System::kLayerState_Initialized)
561         {
562             if (sRemainingSystemLayerEventDelay == 0)
563             {
564                 gSystemLayer.DispatchEvents();
565                 sRemainingSystemLayerEventDelay = gNetworkOptions.EventDelay;
566             }
567             else
568                 sRemainingSystemLayerEventDelay--;
569
570             // TODO: Currently timers are delayed by aSleepTime above. A improved solution would have a mechanism to reduce
571             // aSleepTime according to the next timer.
572
573             gSystemLayer.HandlePlatformTimer();
574         }
575 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
576     }
577
578 #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
579 #if CHIP_TARGET_STYLE_UNIX
580     // TapAddrAutoconf and TapInterface are only needed for LwIP on
581     // sockets simulation in which a host tap/tun interface is used to
582     // proxy the LwIP stack onto a host native network interface.
583     // CollectTapAddresses() is only available on such targets.
584
585     TapInterface_Select(&(sTapIFs[0]), &(sNetIFs[0]), aSleepTime, gNetworkOptions.TapDeviceName.size());
586 #endif // CHIP_TARGET_STYLE_UNIX
587 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
588
589     if (gInet.State == InetLayer::kState_Initialized)
590     {
591 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
592
593         gInet.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
594
595 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
596     }
597 }
598
599 #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
600 static bool NetworkIsReady()
601 {
602     bool ready = true;
603
604     for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
605     {
606         for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
607         {
608             if (!ip6_addr_isany(netif_ip6_addr(&(sNetIFs[j]), i)) && ip6_addr_istentative(netif_ip6_addr_state(&(sNetIFs[j]), i)))
609             {
610                 ready = false;
611                 break;
612             }
613         }
614     }
615     return ready;
616 }
617
618 static void OnLwIPInitComplete(void * arg)
619 {
620     printf("Waiting for addresses assignment...\n");
621 }
622
623 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
624
625 void ShutdownNetwork()
626 {
627     gInet.Shutdown();
628 #if CHIP_SYSTEM_CONFIG_USE_LWIP
629     ReleaseLwIP();
630 #endif
631 }
632
633 void DumpMemory(const uint8_t * mem, uint32_t len, const char * prefix, uint32_t rowWidth)
634 {
635     int indexWidth = snprintf(nullptr, 0, "%X", len);
636
637     if (indexWidth < 4)
638         indexWidth = 4;
639
640     for (uint32_t i = 0; i < len; i += rowWidth)
641     {
642         printf("%s%0*X: ", prefix, indexWidth, i);
643
644         uint32_t rowEnd = i + rowWidth;
645
646         uint32_t j = i;
647         for (; j < rowEnd && j < len; j++)
648             printf("%02X ", mem[j]);
649
650         for (; j < rowEnd; j++)
651             printf("   ");
652
653         for (j = i; j < rowEnd && j < len; j++)
654             if (isprint(static_cast<char>(mem[j])))
655                 printf("%c", mem[j]);
656             else
657                 printf(".");
658
659         printf("\n");
660     }
661 }
662
663 void DumpMemory(const uint8_t * mem, uint32_t len, const char * prefix)
664 {
665     const uint32_t kRowWidth = 16;
666
667     DumpMemory(mem, len, prefix, kRowWidth);
668 }
669
670 static void RebootCallbackFn()
671 {
672     size_t i;
673     size_t j = 0;
674     chip::Platform::ScopedMemoryBuffer<char *> lArgv;
675     if (!lArgv.Alloc(static_cast<size_t>(sRestartCallbackCtx.mArgc + 2)))
676     {
677         printf("** failed to allocate memory **\n");
678         ExitNow();
679     }
680
681     if (gSigusr1Received)
682     {
683         printf("** skipping restart case after SIGUSR1 **\n");
684         ExitNow();
685     }
686
687     for (i = 0; sRestartCallbackCtx.mArgv[i] != nullptr; i++)
688     {
689         if (strcmp(sRestartCallbackCtx.mArgv[i], "--faults") == 0)
690         {
691             // Skip the --faults argument for now
692             i++;
693             continue;
694         }
695         lArgv[j++] = sRestartCallbackCtx.mArgv[i];
696     }
697
698     lArgv[j] = nullptr;
699
700     for (size_t idx = 0; lArgv[idx] != nullptr; idx++)
701     {
702         printf("argv[%d]: %s\n", static_cast<int>(idx), lArgv[idx]);
703     }
704
705     // Need to close any open file descriptor above stdin/out/err.
706     // There is no portable way to get the max fd number.
707     // Given that CHIP's test apps don't open a large number of files,
708     // FD_SETSIZE should be a reasonable upper bound (see the documentation
709     // of select).
710     for (int fd = 3; fd < FD_SETSIZE; fd++)
711     {
712         close(fd);
713     }
714
715     printf("********** Restarting *********\n");
716     fflush(stdout);
717     execvp(lArgv[0], lArgv.Get());
718
719 exit:
720     return;
721 }
722
723 static void PostInjectionCallbackFn(nl::FaultInjection::Manager * aManager, nl::FaultInjection::Identifier aId,
724                                     nl::FaultInjection::Record * aFaultRecord)
725 {
726     uint16_t numargs = aFaultRecord->mNumArguments;
727     uint16_t i;
728
729     printf("***** Injecting fault %s_%s, instance number: %u; reboot: %s", aManager->GetName(), aManager->GetFaultNames()[aId],
730            aFaultRecord->mNumTimesChecked, aFaultRecord->mReboot ? "yes" : "no");
731     if (numargs)
732     {
733         printf(" with %u args:", numargs);
734
735         for (i = 0; i < numargs; i++)
736         {
737             printf(" %d", aFaultRecord->mArguments[i]);
738         }
739     }
740
741     printf("\n");
742 }
743
744 static bool PrintFaultInjectionMaxArgCbFn(nl::FaultInjection::Manager & mgr, nl::FaultInjection::Identifier aId,
745                                           nl::FaultInjection::Record * aFaultRecord, void * aContext)
746 {
747     const char * faultName = mgr.GetFaultNames()[aId];
748
749     if (gFaultInjectionOptions.PrintFaultCounters && aFaultRecord->mNumArguments)
750     {
751         printf("FI_instance_params: %s_%s_s%u maxArg: %u;\n", mgr.GetName(), faultName, aFaultRecord->mNumTimesChecked,
752                aFaultRecord->mArguments[0]);
753     }
754
755     return false;
756 }
757
758 static bool PrintCHIPFaultInjectionMaxArgCbFn(nl::FaultInjection::Identifier aId, nl::FaultInjection::Record * aFaultRecord,
759                                               void * aContext)
760 {
761     nl::FaultInjection::Manager & mgr = chip::FaultInjection::GetManager();
762
763     return PrintFaultInjectionMaxArgCbFn(mgr, aId, aFaultRecord, aContext);
764 }
765
766 static bool PrintSystemFaultInjectionMaxArgCbFn(nl::FaultInjection::Identifier aId, nl::FaultInjection::Record * aFaultRecord,
767                                                 void * aContext)
768 {
769     nl::FaultInjection::Manager & mgr = chip::System::FaultInjection::GetManager();
770
771     return PrintFaultInjectionMaxArgCbFn(mgr, aId, aFaultRecord, aContext);
772 }
773
774 void SetupFaultInjectionContext(int argc, char * argv[])
775 {
776     SetupFaultInjectionContext(argc, argv, nullptr, nullptr);
777 }
778
779 void SetupFaultInjectionContext(int argc, char * argv[], int32_t (*aNumEventsAvailable)(),
780                                 void (*aInjectAsyncEvents)(int32_t index))
781 {
782     nl::FaultInjection::Manager & weavemgr  = chip::FaultInjection::GetManager();
783     nl::FaultInjection::Manager & systemmgr = chip::System::FaultInjection::GetManager();
784
785     sRestartCallbackCtx.mArgc = argc;
786     sRestartCallbackCtx.mArgv = argv;
787
788     nl::FaultInjection::SetGlobalContext(&sFaultInjectionGlobalContext);
789
790     memset(&sFuzzECHeaderCb, 0, sizeof(sFuzzECHeaderCb));
791     sFuzzECHeaderCb.mCallBackFn = PrintCHIPFaultInjectionMaxArgCbFn;
792     weavemgr.InsertCallbackAtFault(chip::FaultInjection::kFault_FuzzExchangeHeaderTx, &sFuzzECHeaderCb);
793
794     if (aNumEventsAvailable && aInjectAsyncEvents)
795     {
796         memset(&sAsyncEventCb, 0, sizeof(sAsyncEventCb));
797         sAsyncEventCb.mCallBackFn = PrintSystemFaultInjectionMaxArgCbFn;
798         systemmgr.InsertCallbackAtFault(chip::System::FaultInjection::kFault_AsyncEvent, &sAsyncEventCb);
799
800         chip::System::FaultInjection::SetAsyncEventCallbacks(aNumEventsAvailable, aInjectAsyncEvents);
801     }
802 }