Coverage Report

Created: 2026-05-06 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openweave-core/src/test-apps/ToolCommon.cpp
Line
Count
Source
1
/*
2
 *
3
 *    Copyright (c) 2013-2018 Nest Labs, Inc.
4
 *    All rights reserved.
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
22
 *      to and used by all Weave test applications and tools.
23
 *
24
 *      NOTE: These do not comprise a public part of the Weave API and
25
 *            are subject to change without notice.
26
 *
27
 */
28
29
#ifndef __STDC_LIMIT_MACROS
30
#define __STDC_LIMIT_MACROS
31
#endif
32
#ifndef __STDC_FORMAT_MACROS
33
#define __STDC_FORMAT_MACROS
34
#endif
35
36
#include <inttypes.h>
37
#include <stdint.h>
38
#include <signal.h>
39
#include <sys/types.h>
40
#include <unistd.h>
41
#include <new>
42
#include <vector>
43
#include "ToolCommon.h"
44
#include "TestGroupKeyStore.h"
45
#include <Weave/Support/NestCerts.h>
46
47
#include <SystemLayer/SystemTimer.h>
48
#include <SystemLayer/SystemFaultInjection.h>
49
#include <Weave/Support/WeaveFaultInjection.h>
50
#include <InetLayer/InetFaultInjection.h>
51
#include <Weave/Support/crypto/WeaveCrypto.h>
52
#include <Weave/Support/crypto/WeaveRNG.h>
53
54
#if WEAVE_CONFIG_ENABLE_TUNNELING
55
#include <InetLayer/TunEndPoint.h>
56
#include <Weave/Profiles/weave-tunneling/WeaveTunnelAgent.h>
57
#endif // WEAVE_CONFIG_ENABLE_TUNNELING
58
59
#include "CASEOptions.h"
60
#include "KeyExportOptions.h"
61
#include "TAKEOptions.h"
62
#include "DeviceDescOptions.h"
63
#include "MockPlatformClocks.h"
64
65
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
66
#include "TapAddrAutoconf.h"
67
#include <lwip/netif.h>
68
#include <netif/etharp.h>
69
#include "TapInterface.h"
70
#include <lwip/tcpip.h>
71
#include <lwip/sys.h>
72
#include <lwip/dns.h>
73
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
74
75
#if CONFIG_BLE_PLATFORM_BLUEZ
76
77
static BleLayer sBle;
78
static nl::Ble::Platform::BlueZ::BluezBleApplicationDelegate sBleApplicationDelegate;
79
static nl::Ble::Platform::BlueZ::BluezBlePlatformDelegate sBlePlatformDelegate(&sBle);
80
81
nl::Ble::Platform::BlueZ::BluezBleApplicationDelegate *getBluezApplicationDelegate()
82
0
{
83
0
    return &sBleApplicationDelegate;
84
0
}
85
86
nl::Ble::Platform::BlueZ::BluezBlePlatformDelegate *getBluezPlatformDelegate()
87
0
{
88
0
    return &sBlePlatformDelegate;
89
0
}
90
91
#endif /* CONFIG_BLE_PLATFORM_BLUEZ */
92
93
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
94
#include <arpa/inet.h>
95
#include <poll.h>
96
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
97
98
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
99
100
static sys_mbox* sLwIPEventQueue = NULL;
101
static unsigned int sLwIPAcquireCount = 0;
102
103
static void AcquireLwIP(void)
104
{
105
    if (sLwIPAcquireCount++ == 0) {
106
        sys_mbox_new(&sLwIPEventQueue, 100);
107
    }
108
}
109
110
static void ReleaseLwIP(void)
111
{
112
    if (sLwIPAcquireCount > 0 && --sLwIPAcquireCount == 0) {
113
        tcpip_finish(NULL, NULL);
114
    }
115
}
116
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
117
118
System::Layer SystemLayer;
119
120
InetLayer Inet;
121
122
#if WEAVE_SYSTEM_CONFIG_USE_LWIP && !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
123
std::vector<TapInterface> tapIFs;
124
std::vector<struct netif> netIFs; // interface to filter
125
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP && !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
126
127
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
128
129
static bool NetworkIsReady();
130
static void OnLwIPInitComplete(void *arg);
131
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
132
133
char DefaultTapDeviceName[32];
134
bool Done = false;
135
bool gSigusr1Received = false;
136
137
uint16_t sTestDefaultUDPSessionKeyId = WeaveKeyId::MakeSessionKeyId(1);
138
uint16_t sTestDefaultTCPSessionKeyId = WeaveKeyId::MakeSessionKeyId(2);
139
uint16_t sTestDefaultSessionKeyId = WeaveKeyId::MakeSessionKeyId(42);
140
141
bool sSuppressAccessControls = false;
142
143
// Perform general *non-network* initialization for test applications
144
void InitToolCommon()
145
0
{
146
0
    WEAVE_ERROR err;
147
0
    unsigned int randSeed;
148
149
    // Initialize the platform secure random data source.  If the underlying random data source is OpenSSL,
150
    // entropy will be acquired via the standard OpenSSL source and the entropy function argument will be
151
    // ignored.  If the underlying random source is the Nest DRBG implementation, or another similar platform
152
    // implementation, entropy will be sourced from /dev/(u)random using the GetDRBGSeedDevRandom() function.
153
0
    err = nl::Weave::Platform::Security::InitSecureRandomDataSource(NULL, 64, NULL, 0);
154
0
    FAIL_ERROR(err, "InitSecureRandomDataSource() failed");
155
156
    // Initialized the rand() generator with a seed from the secure random data source.
157
0
    err = nl::Weave::Platform::Security::GetSecureRandomData((uint8_t *)&randSeed, sizeof(randSeed));
158
0
    FAIL_ERROR(err, "Random number generator seeding failed");
159
0
    srand(randSeed);
160
161
0
    UseStdoutLineBuffering();
162
163
    // Force the linker to link the mock versions of the platform time functions.  This overrides the default
164
    // platform implementations supplied in the Weave library.
165
0
    MockPlatform::gMockPlatformClocks.GetClock_Monotonic();
166
0
}
167
168
static void ExitOnSIGUSR1Handler(int signum)
169
0
{
170
    // exit() allows us a slightly better clean up (gcov data) than SIGINT's exit
171
0
    exit(0);
172
0
}
173
174
// We set a hook to exit when we receive SIGUSR1, SIGTERM or SIGHUP
175
void SetSIGUSR1Handler(void)
176
0
{
177
0
    SetSignalHandler(ExitOnSIGUSR1Handler);
178
0
}
179
180
void DoneOnHandleSIGUSR1(int signum)
181
0
{
182
0
    Done = true;
183
0
    gSigusr1Received = true;
184
0
}
185
186
void SetSignalHandler(SignalHandler handler)
187
0
{
188
0
    struct sigaction sa;
189
0
    int signals[] = { SIGUSR1 };
190
0
    size_t i;
191
192
0
    memset(&sa, 0, sizeof(sa));
193
0
    sa.sa_handler = handler;
194
195
0
    for (i = 0; i < sizeof(signals)/sizeof(signals[0]); i++)
196
0
    {
197
0
        if (sigaction(signals[i], &sa, NULL) == -1)
198
0
        {
199
0
            perror("Can't catch signal");
200
0
            exit(1);
201
0
        }
202
0
    }
203
0
}
204
205
void UseStdoutLineBuffering()
206
0
{
207
    // Set stdout to be line buffered with a buffer of 512 (will flush on new line
208
    // or when the buffer of 512 is exceeded).
209
0
    setvbuf(stdout, NULL, _IOLBF, 512);
210
0
}
211
212
#if WEAVE_CONFIG_ENABLE_TUNNELING
213
214
#if !WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS
215
216
#if !WEAVE_SYSTEM_CONFIG_USE_LWIP
217
    /*
218
     * Some structs are defined redundantly in netinet/in.h and linux/ipv6.h.
219
     * So, cannot include both headers. Define struct in6_ifreq here.
220
     * Copied from linux/ipv6.h
221
     */
222
    struct in6_ifreq
223
    {
224
        struct    in6_addr ifr6_addr;
225
        uint32_t  ifr6_prefixlen;
226
        int       ifr6_ifindex;
227
    };
228
#endif
229
230
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
231
static INET_ERROR InterfaceAddAddress_LwIP(InterfaceId tunIf, IPAddress ipAddr, uint8_t prefixLen)
232
{
233
    INET_ERROR err = INET_NO_ERROR;
234
235
    // Lock LwIP stack
236
237
    LOCK_TCPIP_CORE();
238
239
    int8_t index;
240
    ip6_addr_t ip6_addr;
241
242
    ip6_addr = ipAddr.ToIPv6();
243
244
    if (ip6_addr_islinklocal(&ip6_addr))
245
    {
246
#if LWIP_VERSION_MAJOR > 1
247
        ip6_addr_set(ip_2_ip6(&tunIf->ip6_addr[0]), &ip6_addr);
248
#else // LWIP_VERSION_MAJOR <= 1
249
        ip6_addr_set(&tunIf->ip6_addr[0], &ip6_addr);
250
#endif // LWIP_VERSION_MAJOR <= 1
251
        index = 0;
252
    }
253
    else
254
    {
255
        // Add an address with a prefix route into the route table.
256
257
        err = System::MapErrorLwIP(netif_add_ip6_address_with_route(tunIf, &ip6_addr, prefixLen, &index));
258
    }
259
260
    // Explicitly set this address as valid to bypass DAD
261
262
    if (index >= 0)
263
    {
264
        netif_ip6_addr_set_state(tunIf, index, IP6_ADDR_VALID);
265
    }
266
267
    // UnLock LwIP stack
268
269
    UNLOCK_TCPIP_CORE();
270
271
    return err;
272
}
273
274
static INET_ERROR InterfaceRemoveAddress_LwIP(InterfaceId tunIf, IPAddress ipAddr, uint8_t prefixLen)
275
{
276
    INET_ERROR err = INET_NO_ERROR;
277
278
    // Lock LwIP stack
279
280
    LOCK_TCPIP_CORE();
281
282
    ip6_addr_t ip6_addr;
283
    ip6_addr = ipAddr.ToIPv6();
284
285
    if (ip6_addr_islinklocal(&ip6_addr))
286
    {
287
#if LWIP_VERSION_MAJOR > 1
288
        ip6_addr_set_zero(ip_2_ip6(&tunIf->ip6_addr[0]));
289
#else // LWIP_VERSION_MAJOR <= 1
290
        ip6_addr_set_zero(&tunIf->ip6_addr[0]);
291
#endif // LWIP_VERSION_MAJOR <= 1
292
    }
293
    else
294
    {
295
        /**
296
         * Look for the address among the list of configured ones on the device
297
         * and delete it.
298
         */
299
        err = System::MapErrorLwIP(netif_remove_ip6_address_with_route(tunIf, &ip6_addr, prefixLen));
300
    }
301
302
    // UnLock LwIP stack
303
304
    UNLOCK_TCPIP_CORE();
305
306
    return err;
307
}
308
309
static INET_ERROR SetRouteToTunnelInterface_LwIP(InterfaceId tunIf, IPPrefix ipPrefix, nl::Inet::TunEndPoint::RouteOp routeAddDel)
310
{
311
    INET_ERROR err = INET_NO_ERROR;
312
    struct ip6_prefix ip6_prefix;
313
314
    // Lock LwIP stack
315
316
    LOCK_TCPIP_CORE();
317
318
    ip6_prefix.addr = ipPrefix.IPAddr.ToIPv6();
319
    ip6_prefix.prefix_len = ipPrefix.Length;
320
    if (routeAddDel == nl::Inet::TunEndPoint::kRouteTunIntf_Add)
321
    {
322
        err = System::MapErrorLwIP(ip6_add_route_entry(&ip6_prefix, tunIf, NULL, NULL));
323
    }
324
    else
325
    {
326
        ip6_remove_route_entry(&ip6_prefix);
327
    }
328
329
    // UnLock LwIP stack
330
331
    UNLOCK_TCPIP_CORE();
332
333
    return err;
334
}
335
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
336
337
#if !WEAVE_SYSTEM_CONFIG_USE_LWIP
338
static INET_ERROR InterfaceAddAddress_Linux(InterfaceId tunIf, IPAddress ipAddr, uint8_t prefixLen)
339
0
{
340
0
    INET_ERROR err = INET_NO_ERROR;
341
0
    int ret    = -1;
342
0
    int sockfd = INET_INVALID_SOCKET_FD;
343
0
    struct in6_ifreq ifr6;
344
0
    uint8_t *p = NULL;
345
346
0
    p = &(ifr6.ifr6_addr.s6_addr[0]);
347
0
    for (int i = 0; i < 4; i++)
348
0
    {
349
0
        nl::Weave::Encoding::LittleEndian::Write32(p, ipAddr.Addr[i]);
350
0
    }
351
352
0
    sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
353
0
    if (sockfd < 0)
354
0
    {
355
0
        ExitNow(err = System::MapErrorPOSIX(errno));
356
0
    }
357
358
    // Copy over the interface index to the in6_ifreq
359
360
0
    ifr6.ifr6_ifindex   = tunIf;
361
0
    ifr6.ifr6_prefixlen = prefixLen;
362
363
    // Set the v6 address on the interface
364
365
0
    ret = ioctl(sockfd, SIOCSIFADDR, &ifr6);
366
0
    if (ret != 0 && errno != EALREADY && errno != EEXIST)
367
0
    {
368
0
        ExitNow(err = System::MapErrorPOSIX(errno));
369
0
    }
370
371
0
exit:
372
0
    if (sockfd >= 0)
373
0
    {
374
0
        close(sockfd);
375
0
    }
376
377
0
    return err;
378
0
}
379
380
static INET_ERROR InterfaceRemoveAddress_Linux(InterfaceId tunIf, IPAddress ipAddr, uint8_t prefixLen)
381
0
{
382
0
    INET_ERROR err = INET_NO_ERROR;
383
0
    int ret     = -1;
384
0
    int sockfd  = INET_INVALID_SOCKET_FD;
385
0
    struct in6_ifreq ifr6;
386
0
    uint8_t *p = NULL;
387
388
0
    sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
389
0
    if (sockfd < 0)
390
0
    {
391
0
        ExitNow(err = System::MapErrorPOSIX(errno));
392
0
    }
393
394
0
    p = &(ifr6.ifr6_addr.s6_addr[0]);
395
0
    for (int i = 0; i < 4; i++)
396
0
    {
397
0
        nl::Weave::Encoding::LittleEndian::Write32(p, ipAddr.Addr[i]);
398
0
    }
399
400
    // Copy over the interface index to the in6_ifreq
401
402
0
    ifr6.ifr6_ifindex   = tunIf;
403
0
    ifr6.ifr6_prefixlen = prefixLen;
404
405
0
    ret = ioctl(sockfd, SIOCDIFADDR, &ifr6);
406
0
    if (ret != 0 && errno != ENOENT)
407
0
    {
408
0
        ExitNow(err = System::MapErrorPOSIX(errno));
409
0
    }
410
411
0
exit:
412
0
    if (sockfd >= 0)
413
0
    {
414
0
        close(sockfd);
415
0
    }
416
417
0
    return err;
418
0
}
419
420
static INET_ERROR SetRouteToTunnelInterface_Linux(InterfaceId tunIf, IPPrefix ipPrefix, nl::Inet::TunEndPoint::RouteOp routeAddDel)
421
0
{
422
0
    INET_ERROR err = INET_NO_ERROR;
423
0
    int ret     = -1;
424
0
    int sockfd  = INET_INVALID_SOCKET_FD;
425
0
    struct ::in6_rtmsg route;
426
427
0
    memset(&route, 0, sizeof(struct in6_rtmsg));
428
429
0
    route.rtmsg_dst = ipPrefix.IPAddr.ToIPv6();
430
0
    route.rtmsg_dst_len = ipPrefix.Length;
431
432
    // Fill in in6_rtmsg flags
433
434
0
    route.rtmsg_flags = RTF_UP;
435
0
    if (ipPrefix.Length == NL_INET_IPV6_MAX_PREFIX_LEN)
436
0
    {
437
0
        route.rtmsg_flags |= RTF_HOST;
438
0
    }
439
0
    route.rtmsg_metric = 1;
440
441
0
    sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
442
0
    if (sockfd < 0)
443
0
    {
444
0
        ExitNow(err = System::MapErrorPOSIX(errno));
445
0
    }
446
447
0
    route.rtmsg_ifindex = tunIf;
448
449
0
    if (routeAddDel == nl::Inet::TunEndPoint::kRouteTunIntf_Add)
450
0
    {
451
        // Add the route to the kernel
452
453
0
        ret = ioctl(sockfd, SIOCADDRT, &route);
454
0
        if (ret != 0 && errno != EALREADY && errno != EEXIST)
455
0
        {
456
0
            ExitNow(err = System::MapErrorPOSIX(errno));
457
0
        }
458
0
    }
459
0
    else
460
0
    {
461
        // Delete the route from the kernel
462
463
0
        ret = ioctl(sockfd, SIOCDELRT, &route);
464
0
        if (ret != 0 && errno != EALREADY && errno != ENOENT)
465
0
        {
466
0
            ExitNow(err = System::MapErrorPOSIX(errno));
467
0
        }
468
0
    }
469
470
0
exit:
471
0
    if (sockfd >= 0)
472
0
    {
473
0
        close(sockfd);
474
0
    }
475
476
0
    return err;
477
0
}
478
#endif // !WEAVE_SYSTEM_CONFIG_USE_LWIP
479
480
/**
481
 * Add an IPv6 address to the tunnel interface.
482
 *
483
 * @note
484
 *  On some platforms, this method returns \c INET_NO_ERROR even when
485
 *  insufficient space is available for another address.
486
 *
487
 * @param[in]  tunIf          The tunnel interface identifier.
488
 *
489
 * @param[in] ipAddr          IPAddress object holding the IPv6 address to be assigned.
490
 *
491
 * @param[in] prefixLen       prefix length for on-link route for this address.
492
 *
493
 * @return INET_NO_ERROR      success: address is added.
494
 * @retval  other             another system or platform error
495
 */
496
INET_ERROR InterfaceAddAddress(InterfaceId tunIf, IPAddress ipAddr, uint8_t prefixLen)
497
0
{
498
0
    INET_ERROR err = INET_NO_ERROR;
499
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
500
    err = InterfaceAddAddress_LwIP(tunIf, ipAddr, prefixLen);
501
#else
502
0
    err = InterfaceAddAddress_Linux(tunIf, ipAddr, prefixLen);
503
0
#endif
504
0
    SuccessOrExit(err);
505
506
0
exit:
507
0
    return err;
508
0
}
509
510
/**
511
 * Remove an IPv6 address from the tunnel interface.
512
 *
513
 * @param[in]   tunIf         The tunnel interface identifier.
514
 *
515
 * @param[in]   ipAddr        the IPAddress to remove.
516
 *
517
 * @param[in]   prefixLen     prefix length for on-link route for this address.
518
 *
519
 * @retval  INET_NO_ERROR     success: address is removed.
520
 * @retval  other             another system or platform error.
521
 */
522
INET_ERROR InterfaceRemoveAddress(InterfaceId tunIf, IPAddress ipAddr, uint8_t prefixLen)
523
0
{
524
0
    INET_ERROR err = INET_NO_ERROR;
525
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
526
    err = InterfaceRemoveAddress_LwIP(tunIf, ipAddr, prefixLen);
527
#else
528
0
    err = InterfaceRemoveAddress_Linux(tunIf, ipAddr, prefixLen);
529
0
#endif
530
0
    SuccessOrExit(err);
531
532
0
exit:
533
0
    return err;
534
0
}
535
536
/**
537
 * Add/Remove an IPv6 route pointing to the tunnel interface.
538
 *
539
 * @note
540
 *  The IP address prefix must be an IPv6 address prefix.
541
 *
542
 * @param[in] tunIf             The tunnel interface identifier.
543
 *
544
 * @param[in] ipPrefix          IPPrefix to route.
545
 *
546
 * @param[in] routeAddDel       Flag indicating route addition or deletion.
547
 *
548
 * @retval  INET_NO_ERROR       success: route operation performed
549
 * @retval  other               another system or platform error
550
 */
551
INET_ERROR SetRouteToTunnelInterface(InterfaceId tunIf, IPPrefix ipPrefix, nl::Inet::TunEndPoint::RouteOp routeAddDel)
552
0
{
553
0
    INET_ERROR err = INET_NO_ERROR;
554
555
    // Only allow prefix length up to 64 bits
556
557
0
    if (ipPrefix.Length > NL_INET_IPV6_DEFAULT_PREFIX_LEN)
558
0
    {
559
0
        ExitNow(err = INET_ERROR_BAD_ARGS);
560
0
    }
561
562
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
563
    err = SetRouteToTunnelInterface_LwIP(tunIf, ipPrefix, routeAddDel);
564
#else
565
0
    err = SetRouteToTunnelInterface_Linux(tunIf, ipPrefix, routeAddDel);
566
0
#endif
567
0
    SuccessOrExit(err);
568
569
0
exit:
570
0
    return err;
571
0
}
572
573
/**
574
 * This is a default implementation in a Standalone setting of the Weave Addressing and
575
 * Routing(WARM) platform adaptation when the Tunnel interface is brought up. This may
576
 * be overridden by asserting the preprocessor definition,
577
 * #WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS.
578
 *
579
 * @param[in]  tunIf      The tunnel interface identifier.
580
 *
581
 */
582
void nl::Weave::Profiles::WeaveTunnel::Platform::TunnelInterfaceUp(InterfaceId tunIf)
583
0
{
584
0
   WEAVE_ERROR err = WEAVE_NO_ERROR;
585
0
   uint64_t globalId = 0;
586
0
   IPAddress tunULAAddr;
587
588
   /*
589
    * Add the WiFi interface ULA address to the tunnel interface to ensure the selection of
590
    * a Weave ULA as the source address for packets originating on the local node but destined
591
    * for addresses reachable via the tunnel. Without this, the default IPv6 source address
592
    * selection algorithm might choose an inappropriate source address, making it impossible
593
    * for the destination node to respond.
594
    */
595
0
   globalId = WeaveFabricIdToIPv6GlobalId(ExchangeMgr.FabricState->FabricId);
596
0
   tunULAAddr = IPAddress::MakeULA(globalId, kWeaveSubnetId_PrimaryWiFi,
597
0
                                   nl::Weave::WeaveNodeIdToIPv6InterfaceId(ExchangeMgr.FabricState->LocalNodeId));
598
0
   err = InterfaceAddAddress(tunIf, tunULAAddr, NL_INET_IPV6_MAX_PREFIX_LEN);
599
0
   if (err != WEAVE_NO_ERROR)
600
0
   {
601
0
       WeaveLogError(WeaveTunnel, "Failed to add host address to Weave tunnel interface\n");
602
0
   }
603
0
}
604
605
/**
606
 * This is a default implementation in a Standalone setting of the Weave Addressing and
607
 * Routing(WARM) platform adaptation when the Tunnel interface is brought down. This may
608
 * be overridden by asserting the preprocessor definition,
609
 * #WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS.
610
 *
611
 * @param[in]  tunIf      The tunnel interface identifier.
612
 *
613
 */
614
void nl::Weave::Profiles::WeaveTunnel::Platform::TunnelInterfaceDown(InterfaceId tunIf)
615
0
{
616
0
    WEAVE_ERROR err = WEAVE_NO_ERROR;
617
0
    uint64_t globalId = 0;
618
0
    IPAddress tunULAAddr;
619
620
    /*
621
     * Remove the WiFi interface ULA address to the tunnel interface added during
622
     * TunnelInterfaceUp() call.
623
     */
624
0
    globalId = WeaveFabricIdToIPv6GlobalId(ExchangeMgr.FabricState->FabricId);
625
0
    tunULAAddr = IPAddress::MakeULA(globalId, kWeaveSubnetId_PrimaryWiFi,
626
0
                                    nl::Weave::WeaveNodeIdToIPv6InterfaceId(ExchangeMgr.FabricState->LocalNodeId));
627
0
    err = InterfaceRemoveAddress(tunIf, tunULAAddr, NL_INET_IPV6_MAX_PREFIX_LEN);
628
0
    if (err != WEAVE_NO_ERROR)
629
0
    {
630
0
        WeaveLogError(WeaveTunnel, "Failed to remove host address from Weave tunnel interface\n");
631
0
    }
632
0
}
633
634
/**
635
 * This is a default implementation in a Standalone setting of the Weave Addressing and
636
 * Routing(WARM) platform adaptation when the Service tunnel connection is established.
637
 * This may be overridden by asserting the preprocessor definition,
638
 * #WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS.
639
 *
640
 * @param[in]  tunIf      The tunnel interface identifier.
641
 *
642
 * @param[in]  tunMode    The mode(Primary, PrimaryAndBackup, BackupOnly) in which the
643
 *                         tunnel is established.
644
 *
645
 */
646
void nl::Weave::Profiles::WeaveTunnel::Platform::ServiceTunnelEstablished(InterfaceId tunIf,
647
                                                                          TunnelAvailabilityMode tunMode)
648
0
{
649
0
    WEAVE_ERROR err = WEAVE_NO_ERROR;
650
0
    IPPrefix prefix;
651
0
    uint64_t globalId = 0;
652
0
    IPAddress tunULAAddr;
653
654
    // Create prefix fd<globalId>::/48 to install route to tunnel interface
655
656
0
    globalId = WeaveFabricIdToIPv6GlobalId(ExchangeMgr.FabricState->FabricId);
657
0
    tunULAAddr = IPAddress::MakeULA(globalId, 0, 0);
658
659
0
    prefix.IPAddr = tunULAAddr;
660
0
    prefix.Length = WEAVE_ULA_FABRIC_DEFAULT_PREFIX_LEN;
661
662
    // Add route to tunnel interface
663
0
    err = SetRouteToTunnelInterface(tunIf, prefix, TunEndPoint::kRouteTunIntf_Add);
664
0
    if (err != WEAVE_NO_ERROR)
665
0
    {
666
0
        WeaveLogError(WeaveTunnel, "Failed to add Weave tunnel route\n");
667
0
    }
668
0
}
669
670
/**
671
 * This is a default implementation in a Standalone setting of the Weave Addressing and
672
 * Routing(WARM) platform adaptation when Border Routing is enabled in Thread or any
673
 * peripheral network.
674
 * This may be overridden by asserting the preprocessor definition,
675
 * #WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS.
676
 *
677
 */
678
void nl::Weave::Profiles::WeaveTunnel::Platform::EnableBorderRouting(void)
679
0
{
680
0
    WeaveLogDetail(WeaveTunnel, "Border Routing enabled\n");
681
0
}
682
683
/**
684
 * This is a default implementation in a Standalone setting of the Weave Addressing and
685
 * Routing(WARM) platform adaptation when Border Routing is disabled in Thread or any
686
 * peripheral network.
687
 * This may be overridden by asserting the preprocessor definition,
688
 * #WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS.
689
 *
690
 */
691
void nl::Weave::Profiles::WeaveTunnel::Platform::DisableBorderRouting(void)
692
0
{
693
0
    WeaveLogDetail(WeaveTunnel, "Border Routing disabled\n");
694
0
}
695
696
/**
697
 * This is a default implementation in a Standalone setting of the Weave Addressing and
698
 * Routing(WARM) platform adaptation when the Service tunnel connection is torn down.
699
 * This may be overridden by asserting the preprocessor definition,
700
 * #WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS.
701
 *
702
 * @param[in]  tunIf      The tunnel interface identifier.
703
 *
704
 */
705
void nl::Weave::Profiles::WeaveTunnel::Platform::ServiceTunnelDisconnected(InterfaceId tunIf)
706
0
{
707
0
    WEAVE_ERROR err = WEAVE_NO_ERROR;
708
0
    IPPrefix prefix;
709
0
    uint64_t globalId = 0;
710
0
    IPAddress tunULAAddr;
711
712
    // Delete route to tunnel interface for prefix fd<globalId>::/48
713
714
0
    globalId = WeaveFabricIdToIPv6GlobalId(ExchangeMgr.FabricState->FabricId);
715
0
    tunULAAddr = IPAddress::MakeULA(globalId, 0, 0);
716
717
0
    prefix.IPAddr = tunULAAddr;
718
0
    prefix.Length = WEAVE_ULA_FABRIC_DEFAULT_PREFIX_LEN;
719
720
    // Delete route
721
722
0
    err = SetRouteToTunnelInterface(tunIf, prefix, TunEndPoint::kRouteTunIntf_Del);
723
0
    if (err != WEAVE_NO_ERROR)
724
0
    {
725
0
        WeaveLogError(WeaveTunnel, "Failed to remove Weave tunnel route\n");
726
0
    }
727
0
}
728
729
/**
730
 * This is a default implementation in a Standalone setting of the Weave Addressing and
731
 * Routing(WARM) platform adaptation when the Service tunnel connection changes mode.
732
 * This may be overridden by asserting the preprocessor definition,
733
 * #WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS.
734
 *
735
 * @param[in]  tunIf      The tunnel interface identifier.
736
 *
737
 * @param[in]  tunMode     The mode(Primary, PrimaryAndBackup, BackupOnly) to which the
738
 *                         tunnel connection has been changed to.
739
 *
740
 */
741
void nl::Weave::Profiles::WeaveTunnel::Platform::ServiceTunnelModeChange(InterfaceId tunIf,
742
                                                                         TunnelAvailabilityMode tunMode)
743
0
{
744
0
    (void)tunIf;
745
0
    (void)tunMode;
746
0
}
747
#endif // WEAVE_TUNNEL_CONFIG_WILL_OVERRIDE_ADDR_ROUTING_FUNCS
748
749
#endif // WEAVE_CONFIG_ENABLE_TUNNELING
750
751
void InitSystemLayer()
752
0
{
753
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
754
    AcquireLwIP();
755
    SystemLayer.Init(sLwIPEventQueue);
756
#else // !WEAVE_SYSTEM_CONFIG_USE_LWIP
757
0
    SystemLayer.Init(NULL);
758
0
#endif // !WEAVE_SYSTEM_CONFIG_USE_LWIP
759
0
}
760
761
void ShutdownSystemLayer()
762
0
{
763
0
    SystemLayer.Shutdown();
764
765
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
766
    ReleaseLwIP();
767
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
768
0
}
769
770
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
771
static void PrintNetworkState()
772
{
773
    char intfName[10];
774
775
    for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
776
    {
777
        struct netif *netIF = &(netIFs[j]);
778
        TapInterface *tapIF = &(tapIFs[j]);
779
780
        GetInterfaceName(netIF, intfName, sizeof(intfName));
781
782
        printf("LwIP interface ready\n");
783
        printf("  Interface Name: %s\n", intfName);
784
        printf("  Tap Device: %s\n", gNetworkOptions.TapDeviceName[j]);
785
        printf("  MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", tapIF->macAddr[0], tapIF->macAddr[1], tapIF->macAddr[2], tapIF->macAddr[3], tapIF->macAddr[4], tapIF->macAddr[5]);
786
#if INET_CONFIG_ENABLE_IPV4
787
        printf("  IPv4 Address: %s\n", ipaddr_ntoa(&(netIF->ip_addr)));
788
        printf("  IPv4 Mask: %s\n", ipaddr_ntoa(&(netIF->netmask)));
789
        printf("  IPv4 Gateway: %s\n", ipaddr_ntoa(&(netIF->gw)));
790
#endif // INET_CONFIG_ENABLE_IPV4
791
        for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
792
        {
793
            if (!ip6_addr_isany(netif_ip6_addr(netIF, i)))
794
            {
795
                printf("  IPv6 address: %s, 0x%02x\n", ip6addr_ntoa(netif_ip6_addr(netIF, i)), netif_ip6_addr_state(netIF, i));
796
            }
797
        }
798
    }
799
#if INET_CONFIG_ENABLE_DNS_RESOLVER
800
    char dnsServerAddrStr[DNS_MAX_NAME_LENGTH];
801
    printf("  DNS Server: %s\n", gNetworkOptions.DNSServerAddr.ToString(dnsServerAddrStr, sizeof(dnsServerAddrStr)));
802
#endif // INET_CONFIG_ENABLE_DNS_RESOLVER
803
}
804
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
805
806
void InitNetwork()
807
0
{
808
0
    void* lContext = NULL;
809
810
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
811
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
812
813
    tcpip_init(NULL, NULL);
814
815
#else // !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
816
817
    // If an tap device name hasn't been specified, derive one from the IPv6 interface id.
818
819
    if (gNetworkOptions.TapDeviceName.empty())
820
    {
821
        for (size_t j = 0; j < gNetworkOptions.LocalIPv6Addr.size(); j++)
822
        {
823
            uint64_t iid = gNetworkOptions.LocalIPv6Addr[j].InterfaceId();
824
            char * tap_name = (char *)malloc(sizeof(DefaultTapDeviceName));
825
            snprintf(tap_name, sizeof(DefaultTapDeviceName), "weave-dev-%" PRIx64, iid & 0xFFFF);
826
            tap_name[ sizeof(DefaultTapDeviceName) - 1] = 0;
827
            gNetworkOptions.TapDeviceName.push_back(tap_name);
828
        }
829
    }
830
831
    err_t lwipErr;
832
833
    tapIFs.clear();
834
    netIFs.clear();
835
    for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
836
    {
837
        TapInterface tapIF;
838
        struct netif netIF;
839
        tapIFs.push_back(tapIF);
840
        netIFs.push_back(netIF);
841
    }
842
843
    for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
844
    {
845
        lwipErr = TapInterface_Init(&(tapIFs[j]), gNetworkOptions.TapDeviceName[j], NULL);
846
        if (lwipErr != ERR_OK)
847
        {
848
            printf("Failed to initialize tap device %s: %s\n", gNetworkOptions.TapDeviceName[j], ErrorStr(System::MapErrorLwIP(lwipErr)));
849
            exit(EXIT_FAILURE);
850
        }
851
    }
852
    tcpip_init(OnLwIPInitComplete, NULL);
853
854
    // Lock LwIP stack
855
    LOCK_TCPIP_CORE();
856
857
    for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
858
    {
859
        std::vector<char *>addrsVec;
860
        addrsVec.clear();
861
        if (gNetworkOptions.TapUseSystemConfig)
862
        {
863
            CollectTapAddresses(addrsVec, gNetworkOptions.TapDeviceName[j]);
864
        }
865
866
#if INET_CONFIG_ENABLE_IPV4
867
868
        IPAddress ip4Addr = (j < gNetworkOptions.LocalIPv4Addr.size())
869
            ? gNetworkOptions.LocalIPv4Addr[j]
870
            : IPAddress::Any;
871
        for (size_t n = 0; n < addrsVec.size(); n++)
872
        {
873
            IPAddress auto_addr;
874
            if (IPAddress::FromString(addrsVec[n], auto_addr) && auto_addr.IsIPv4())
875
            {
876
                ip4Addr = auto_addr;
877
            }
878
        }
879
880
        IPAddress ip4Gateway = (j < gNetworkOptions.IPv4GatewayAddr.size())
881
            ? gNetworkOptions.IPv4GatewayAddr[j]
882
            : IPAddress::Any;
883
884
        {
885
#if LWIP_VERSION_MAJOR > 1
886
            ip4_addr_t ip4AddrLwIP, ip4NetmaskLwIP, ip4GatewayLwIP;
887
#else // LWIP_VERSION_MAJOR <= 1
888
            ip_addr_t ip4AddrLwIP, ip4NetmaskLwIP, ip4GatewayLwIP;
889
#endif // LWIP_VERSION_MAJOR <= 1
890
891
            ip4AddrLwIP = ip4Addr.ToIPv4();
892
            IP4_ADDR(&ip4NetmaskLwIP, 255, 255, 255, 0);
893
            ip4GatewayLwIP = ip4Gateway.ToIPv4();
894
            netif_add(&(netIFs[j]), &ip4AddrLwIP, &ip4NetmaskLwIP, &ip4GatewayLwIP, &(tapIFs[j]), TapInterface_SetupNetif, tcpip_input);
895
        }
896
897
#endif // INET_CONFIG_ENABLE_IPV4
898
899
        netif_create_ip6_linklocal_address(&(netIFs[j]), 1);
900
901
        if (j < gNetworkOptions.LocalIPv6Addr.size())
902
        {
903
            ip6_addr_t ip6addr = gNetworkOptions.LocalIPv6Addr[j].ToIPv6();
904
            s8_t index;
905
            netif_add_ip6_address_with_route(&(netIFs[j]), &ip6addr, 64, &index);
906
            // add ipv6 route for ipv6 address
907
            if (j < gNetworkOptions.IPv6GatewayAddr.size())
908
            {
909
                static ip6_addr_t br_ip6_addr = gNetworkOptions.IPv6GatewayAddr[j].ToIPv6();
910
                struct ip6_prefix ip6_prefix;
911
                ip6_prefix.addr = nl::Inet::IPAddress::Any.ToIPv6();
912
                ip6_prefix.prefix_len = 0;
913
                ip6_add_route_entry(&ip6_prefix, &netIFs[j], &br_ip6_addr, NULL);
914
            }
915
            if (index >= 0)
916
            {
917
                netif_ip6_addr_set_state(&(netIFs[j]), index, IP6_ADDR_PREFERRED);
918
            }
919
        }
920
        for (size_t n = 0; n < addrsVec.size(); n++)
921
        {
922
            IPAddress auto_addr;
923
            if (IPAddress::FromString(addrsVec[n], auto_addr) && !auto_addr.IsIPv4())
924
            {
925
                ip6_addr_t ip6addr = auto_addr.ToIPv6();
926
                s8_t index;
927
                if (auto_addr.IsIPv6LinkLocal())
928
                    continue; // skip over the LLA addresses, LwIP is aready adding those
929
                if (auto_addr.IsIPv6Multicast())
930
                    continue; // skip over the multicast addresses from host for now.
931
                netif_add_ip6_address_with_route(&(netIFs[j]), &ip6addr, 64, &index);
932
                if (index >= 0)
933
                {
934
                    netif_ip6_addr_set_state(&(netIFs[j]), index, IP6_ADDR_PREFERRED);
935
                }
936
            }
937
        }
938
939
        netif_set_up(&(netIFs[j]));
940
        netif_set_link_up(&(netIFs[j]));
941
942
    }
943
944
    netif_set_default(&(netIFs[0]));
945
    // UnLock LwIP stack
946
947
    UNLOCK_TCPIP_CORE();
948
949
950
    while (!NetworkIsReady())
951
    {
952
        struct timeval lSleepTime;
953
        lSleepTime.tv_sec = 0;
954
        lSleepTime.tv_usec = 100000;
955
        ServiceEvents(lSleepTime);
956
    }
957
958
    //FIXME: this is kinda nasty :(
959
    // Force new IP address to be ready, bypassing duplicate detection.
960
961
    for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
962
    {
963
        if (j < gNetworkOptions.LocalIPv6Addr.size()) {
964
            netif_ip6_addr_set_state(&(netIFs[j]), 2, 0x30);
965
        }
966
        else
967
        {
968
            netif_ip6_addr_set_state(&(netIFs[j]), 1, 0x30);
969
        }
970
    }
971
972
#if INET_CONFIG_ENABLE_DNS_RESOLVER
973
    if (gNetworkOptions.DNSServerAddr != IPAddress::Any)
974
    {
975
#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
976
        ip_addr_t dnsServerAddr = gNetworkOptions.DNSServerAddr.ToLwIPAddr();
977
#else // LWIP_VERSION_MAJOR <= 1
978
#if INET_CONFIG_ENABLE_IPV4
979
        ip_addr_t dnsServerAddr = gNetworkOptions.DNSServerAddr.ToIPv4();
980
#else // !INET_CONFIG_ENABLE_IPV4
981
#error "No support for DNS Resolver without IPv4!"
982
#endif // !INET_CONFIG_ENABLE_IPV4
983
#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
984
985
        dns_setserver(0, &dnsServerAddr);
986
    }
987
#endif // INET_CONFIG_ENABLE_DNS_RESOLVER
988
989
    PrintNetworkState();
990
991
#endif // !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
992
993
    AcquireLwIP();
994
    lContext = sLwIPEventQueue;
995
996
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
997
998
0
    Inet.Init(SystemLayer, lContext);
999
0
}
1000
1001
void ServiceEvents(::timeval& aSleepTime)
1002
0
{
1003
0
    static bool printed = false;
1004
0
    if (!printed)
1005
0
    {
1006
#if WEAVE_SYSTEM_CONFIG_USE_LWIP && !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1007
        if (NetworkIsReady())
1008
#endif
1009
0
        {
1010
0
            printf("Weave Node ready to service events; PID: %d; PPID: %d\n", getpid(), getppid());
1011
0
            fflush(stdout);
1012
0
            printed = true;
1013
0
        }
1014
0
    }
1015
0
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1016
0
    int sleepTime = aSleepTime.tv_usec / 1000 + aSleepTime.tv_sec * 1000;
1017
0
    struct pollfd pollFDs[WEAVE_CONFIG_MAX_POLL_FDS];
1018
0
    int numPollFDs = 0;
1019
1020
0
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1021
0
    if (SystemLayer.State() == System::kLayerState_Initialized)
1022
0
        SystemLayer.PrepareSelect(pollFDs, numPollFDs, sleepTime);
1023
0
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1024
1025
0
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1026
0
    if (Inet.State == InetLayer::kState_Initialized)
1027
0
        Inet.PrepareSelect(pollFDs, numPollFDs, sleepTime);
1028
0
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1029
1030
0
    int pollRes = poll(pollFDs, numPollFDs, sleepTime);
1031
0
    if (pollRes < 0)
1032
0
    {
1033
0
        printf("poll failed: %s\n", ErrorStr(System::MapErrorPOSIX(errno)));
1034
0
        return;
1035
0
    }
1036
1037
0
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1038
1039
0
    if (SystemLayer.State() == System::kLayerState_Initialized)
1040
0
    {
1041
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
1042
        static uint32_t sRemainingSystemLayerEventDelay = 0;
1043
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
1044
1045
0
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1046
1047
0
        SystemLayer.HandleSelectResult(pollFDs, numPollFDs);
1048
1049
0
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1050
1051
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
1052
        if (SystemLayer.State() == System::kLayerState_Initialized)
1053
        {
1054
            if (sRemainingSystemLayerEventDelay == 0)
1055
            {
1056
                SystemLayer.DispatchEvents();
1057
                sRemainingSystemLayerEventDelay = gNetworkOptions.EventDelay;
1058
1059
            }
1060
            else
1061
                sRemainingSystemLayerEventDelay--;
1062
1063
            // TODO: Currently timers are delayed by aSleepTime above. A improved solution would have a mechanism to reduce
1064
            // aSleepTime according to the next timer.
1065
1066
            SystemLayer.HandlePlatformTimer();
1067
1068
        }
1069
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
1070
0
    }
1071
1072
#if WEAVE_SYSTEM_CONFIG_USE_LWIP && !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1073
    TapInterface_Select(&(tapIFs[0]), &(netIFs[0]), aSleepTime, gNetworkOptions.TapDeviceName.size());
1074
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP && !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1075
1076
0
    if (Inet.State == InetLayer::kState_Initialized)
1077
0
    {
1078
#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES && WEAVE_SYSTEM_CONFIG_USE_LWIP
1079
        static uint32_t sRemainingInetLayerEventDelay = 0;
1080
#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES && WEAVE_SYSTEM_CONFIG_USE_LWIP
1081
1082
0
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1083
1084
0
        Inet.HandleSelectResult(pollFDs, numPollFDs);
1085
1086
0
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1087
1088
#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES && WEAVE_SYSTEM_CONFIG_USE_LWIP
1089
        if (Inet.State == InetLayer::kState_Initialized)
1090
        {
1091
            if (sRemainingInetLayerEventDelay == 0)
1092
            {
1093
                Inet.DispatchEvents();
1094
                sRemainingInetLayerEventDelay = gNetworkOptions.EventDelay;
1095
            }
1096
            else
1097
                sRemainingInetLayerEventDelay--;
1098
1099
            // TODO: Currently timers are delayed by aSleepTime above. A improved solution would have a mechanism to reduce
1100
            // aSleepTime according to the next timer.
1101
1102
            Inet.HandlePlatformTimer();
1103
1104
        }
1105
#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES && WEAVE_SYSTEM_CONFIG_USE_LWIP
1106
0
    }
1107
0
}
1108
1109
#if WEAVE_SYSTEM_CONFIG_USE_LWIP && !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1110
1111
static bool NetworkIsReady()
1112
{
1113
    bool ready = true;
1114
1115
    for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
1116
    {
1117
        for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
1118
        {
1119
            if (!ip6_addr_isany(netif_ip6_addr(&(netIFs[j]), i)) && ip6_addr_istentative(netif_ip6_addr_state(&(netIFs[j]), i)))
1120
            {
1121
                ready = false;
1122
                break;
1123
            }
1124
        }
1125
    }
1126
    return ready;
1127
}
1128
1129
static void OnLwIPInitComplete(void *arg)
1130
{
1131
    printf("Waiting for addresses assignment...\n");
1132
}
1133
1134
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP && !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
1135
1136
void InitWeaveStack(bool listen, bool initExchangeMgr)
1137
0
{
1138
0
    WEAVE_ERROR res;
1139
0
    WeaveMessageLayer::InitContext initContext;
1140
0
    static nlDEFINE_ALIGNED_VAR(sTestGroupKeyStore, sizeof(TestGroupKeyStore), void*);
1141
1142
0
#if CONFIG_BLE_PLATFORM_BLUEZ
1143
    // Initialize the BleLayer object.
1144
0
    res = sBle.Init(&sBlePlatformDelegate, &sBleApplicationDelegate, &SystemLayer);
1145
1146
0
    if (res != WEAVE_NO_ERROR)
1147
0
    {
1148
0
        printf("sBle.Init failed: %s\n", ErrorStr(res));
1149
0
        exit(-1);
1150
0
    }
1151
0
#endif /* CONFIG_BLE_PLATFORM_BLUEZ */
1152
1153
0
    nl::Weave::Stats::SetObjects(&MessageLayer);
1154
1155
    // Seed the random number generator
1156
1157
0
    System::Timer::Epoch now = System::Timer::GetCurrentEpoch();
1158
0
    srand((unsigned int) now);
1159
1160
    // Initialize the FabricState object.
1161
1162
0
    res = FabricState.Init(new (&sTestGroupKeyStore) TestGroupKeyStore());
1163
0
    if (res != WEAVE_NO_ERROR)
1164
0
    {
1165
0
        printf("FabricState.Init failed: %s\n", ErrorStr(res));
1166
0
        exit(EXIT_FAILURE);
1167
0
    }
1168
1169
0
    FabricState.FabricId = gWeaveNodeOptions.FabricId;
1170
0
    FabricState.LocalNodeId = gWeaveNodeOptions.LocalNodeId;
1171
0
    FabricState.DefaultSubnet = gWeaveNodeOptions.SubnetId;
1172
0
    FabricState.PairingCode = gWeaveNodeOptions.PairingCode;
1173
1174
    // When using sockets we must listen on specific addresses, rather than ANY. Otherwise you will only be
1175
    // able to run a single Weave application per system.
1176
1177
0
#if WEAVE_CONFIG_ENABLE_TARGETED_LISTEN
1178
0
#if INET_CONFIG_ENABLE_IPV4
1179
0
    if (!gNetworkOptions.LocalIPv4Addr.empty())
1180
0
        FabricState.ListenIPv4Addr = gNetworkOptions.LocalIPv4Addr[0];
1181
0
#endif // INET_CONFIG_ENABLE_IPV4
1182
1183
0
    if (!gNetworkOptions.LocalIPv6Addr.empty())
1184
0
        FabricState.ListenIPv6Addr = gNetworkOptions.LocalIPv6Addr[0];
1185
0
#endif
1186
1187
0
#if WEAVE_CONFIG_SECURITY_TEST_MODE
1188
0
    FabricState.LogKeys = true;
1189
0
#endif
1190
1191
    // Initialize the WeaveMessageLayer object.
1192
    // TODO mock-device BLE support?
1193
1194
0
    initContext.systemLayer = &SystemLayer;
1195
0
    initContext.inet = &Inet;
1196
0
    initContext.fabricState = &FabricState;
1197
0
    initContext.listenTCP = listen;
1198
0
    initContext.listenUDP = true;
1199
0
#if WEAVE_CONFIG_ENABLE_EPHEMERAL_UDP_PORT
1200
0
    initContext.enableEphemeralUDPPort = gWeaveNodeOptions.UseEphemeralUDPPort;
1201
0
#endif // WEAVE_CONFIG_ENABLE_EPHEMERAL_UDP_PORT
1202
1203
0
#if CONFIG_BLE_PLATFORM_BLUEZ
1204
0
    initContext.ble = &sBle;
1205
0
    initContext.listenBLE = true;
1206
0
#endif /* CONFIG_NETWORK_LAYER_BLE */
1207
1208
0
    res = MessageLayer.Init(&initContext);
1209
0
    if (res != WEAVE_NO_ERROR)
1210
0
    {
1211
0
        printf("WeaveMessageLayer.Init failed: %s\n", ErrorStr(res));
1212
0
        exit(EXIT_FAILURE);
1213
0
    }
1214
1215
0
    if (initExchangeMgr)
1216
0
    {
1217
        // Initialize the Exchange Manager object.
1218
1219
0
        res = ExchangeMgr.Init(&MessageLayer);
1220
0
        if (res != WEAVE_NO_ERROR)
1221
0
        {
1222
0
            printf("WeaveExchangeManager.Init failed: %s\n", ErrorStr(res));
1223
0
            exit(EXIT_FAILURE);
1224
0
        }
1225
1226
0
        res = SecurityMgr.Init(ExchangeMgr, SystemLayer);
1227
0
        if (res != WEAVE_NO_ERROR)
1228
0
        {
1229
0
            printf("WeaveSecurityManager.Init failed: %s\n", ErrorStr(res));
1230
0
            exit(EXIT_FAILURE);
1231
0
        }
1232
0
        SecurityMgr.IdleSessionTimeout = gGeneralSecurityOptions.GetIdleSessionTimeout();
1233
0
        SecurityMgr.SessionEstablishTimeout = gGeneralSecurityOptions.GetSessionEstablishmentTimeout();
1234
1235
0
        if (gTAKEOptions.ForceReauth)
1236
0
        {
1237
0
            res = gTAKEOptions.PrepopulateTokenData();
1238
0
            if (res != WEAVE_NO_ERROR)
1239
0
            {
1240
0
                printf("MockTAKEChallengerDelegate::StoreTokenAuthData failed: %s\n", ErrorStr(res));
1241
0
                exit(EXIT_FAILURE);
1242
0
            }
1243
0
        }
1244
1245
0
        SecurityMgr.SetCASEAuthDelegate(&gCASEOptions);
1246
0
        SecurityMgr.SetKeyExportDelegate(&gKeyExportOptions);
1247
0
        SecurityMgr.SetTAKEAuthDelegate(&gMockTAKEChallengerDelegate);
1248
0
        SecurityMgr.SetTAKETokenAuthDelegate(&gMockTAKETokenDelegate);
1249
1250
0
#if WEAVE_CONFIG_ENABLE_CASE_INITIATOR
1251
0
        if (gCASEOptions.InitiatorCASEConfig != kCASEConfig_NotSpecified)
1252
0
            SecurityMgr.InitiatorCASEConfig = gCASEOptions.InitiatorCASEConfig;
1253
0
#endif
1254
0
        if (gCASEOptions.AllowedCASEConfigs != 0)
1255
0
        {
1256
0
#if WEAVE_CONFIG_ENABLE_CASE_INITIATOR
1257
0
            SecurityMgr.InitiatorAllowedCASEConfigs = gCASEOptions.AllowedCASEConfigs;
1258
0
#endif
1259
0
#if WEAVE_CONFIG_ENABLE_CASE_RESPONDER
1260
0
            SecurityMgr.ResponderAllowedCASEConfigs = gCASEOptions.AllowedCASEConfigs;
1261
0
#endif
1262
0
        }
1263
1264
0
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
1265
0
        if (gKeyExportOptions.AllowedKeyExportConfigs != 0)
1266
0
            SecurityMgr.ResponderAllowedKeyExportConfigs = gKeyExportOptions.AllowedKeyExportConfigs;
1267
0
#endif
1268
1269
0
#if WEAVE_CONFIG_SECURITY_TEST_MODE
1270
0
        SecurityMgr.CASEUseKnownECDHKey = gCASEOptions.UseKnownECDHKey;
1271
0
#endif
1272
0
    }
1273
0
}
1274
1275
void PrintNodeConfig()
1276
0
{
1277
1278
0
    printf("Weave Node Configuration:\n");
1279
0
    printf("  Fabric Id: %" PRIX64 "\n", FabricState.FabricId);
1280
0
    printf("  Subnet Number: %X\n", FabricState.DefaultSubnet);
1281
0
    printf("  Node Id: %" PRIX64 "\n", FabricState.LocalNodeId);
1282
1283
0
    if (MessageLayer.IsListening)
1284
0
    {
1285
0
        printf("  Listening Addresses:");
1286
0
#if WEAVE_CONFIG_ENABLE_TARGETED_LISTEN
1287
0
        char nodeAddrStr[64];
1288
1289
0
        if (FabricState.ListenIPv6Addr == IPAddress::Any
1290
0
#if INET_CONFIG_ENABLE_IPV4
1291
0
            && FabricState.ListenIPv4Addr == IPAddress::Any
1292
0
#endif // INET_CONFIG_ENABLE_IPV4
1293
0
            )
1294
0
            printf(" any\n");
1295
0
        else
1296
0
        {
1297
0
            printf("\n");
1298
0
            if (FabricState.ListenIPv6Addr != IPAddress::Any)
1299
0
            {
1300
0
                FabricState.ListenIPv6Addr.ToString(nodeAddrStr, sizeof(nodeAddrStr));
1301
0
                printf("      %s (ipv6)\n", nodeAddrStr);
1302
0
            }
1303
1304
0
#if INET_CONFIG_ENABLE_IPV4
1305
0
            if (FabricState.ListenIPv4Addr != IPAddress::Any)
1306
0
            {
1307
0
                FabricState.ListenIPv4Addr.ToString(nodeAddrStr, sizeof(nodeAddrStr));
1308
0
                printf("      %s (ipv4)\n", nodeAddrStr);
1309
0
            }
1310
0
#endif // INET_CONFIG_ENABLE_IPV4
1311
0
        }
1312
#else // WEAVE_CONFIG_ENABLE_TARGETED_LISTEN
1313
        printf(" any\n");
1314
#endif // WEAVE_CONFIG_ENABLE_TARGETED_LISTEN
1315
0
    }
1316
0
}
1317
1318
void ShutdownNetwork()
1319
0
{
1320
0
    Inet.Shutdown();
1321
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
1322
    ReleaseLwIP();
1323
#endif
1324
0
}
1325
1326
void ShutdownWeaveStack()
1327
0
{
1328
0
    SecurityMgr.Shutdown();
1329
0
    ExchangeMgr.Shutdown();
1330
0
    MessageLayer.Shutdown();
1331
0
    FabricState.Shutdown();
1332
0
}
1333
1334
void DumpMemory(const uint8_t *mem, uint32_t len, const char *prefix, uint32_t rowWidth)
1335
0
{
1336
0
    (void) DumpMemory;
1337
1338
0
    int indexWidth = snprintf(NULL, 0, "%X", len);
1339
0
    if (indexWidth < 4)
1340
0
        indexWidth = 4;
1341
1342
0
    for (uint32_t i = 0; i < len; i += rowWidth)
1343
0
    {
1344
0
        printf("%s%0*X: ", prefix, indexWidth, i);
1345
1346
0
        uint32_t rowEnd = i + rowWidth;
1347
1348
0
        uint32_t j = i;
1349
0
        for (; j < rowEnd && j < len; j++)
1350
0
            printf("%02X ", mem[j]);
1351
1352
0
        for (; j < rowEnd; j++)
1353
0
            printf("   ");
1354
1355
0
        for (j = i; j < rowEnd && j < len; j++)
1356
0
            if (isprint((char) mem[j]))
1357
0
                printf("%c", mem[j]);
1358
0
            else
1359
0
                printf(".");
1360
1361
0
        printf("\n");
1362
0
    }
1363
0
}
1364
1365
void DumpMemoryCStyle(const uint8_t *mem, uint32_t len, const char *prefix, uint32_t rowWidth)
1366
0
{
1367
0
    (void) DumpMemoryCStyle;
1368
1369
0
    for (uint32_t i = 0; i < len; i += rowWidth)
1370
0
    {
1371
0
        printf("%s", prefix);
1372
1373
0
        uint32_t rowEnd = i + rowWidth;
1374
1375
0
        uint32_t j = i;
1376
0
        for (; j < rowEnd && j < len; j++)
1377
0
            printf("0x%02X, ", mem[j]);
1378
1379
0
        printf("\n");
1380
0
    }
1381
0
}
1382
1383
bool IsZeroBytes(const uint8_t *buf, uint32_t len)
1384
0
{
1385
0
    for (; len > 0; len--, buf++)
1386
0
        if (*buf != 0)
1387
0
            return false;
1388
0
    return true;
1389
0
}
1390
1391
void PrintMACAddress(const uint8_t *buf, uint32_t len)
1392
0
{
1393
0
    for (; len > 0; buf++, len--)
1394
0
    {
1395
0
        if (len != 1)
1396
0
            printf("%02X:", (unsigned)*buf);
1397
0
        else
1398
0
            printf("%02X", (unsigned)*buf);
1399
0
    }
1400
0
}
1401
1402
void PrintAddresses()
1403
0
{
1404
0
    InterfaceAddressIterator iterator;
1405
0
    printf("Valid addresses: \n");
1406
0
    for (; iterator.HasCurrent(); iterator.Next()) {
1407
0
        IPAddress addr = iterator.GetAddress();
1408
0
        char buf[80];
1409
0
        addr.ToString(buf, 80);
1410
0
        printf("%s\n", buf);
1411
0
    }
1412
0
}
1413
1414
uint8_t *ReadFileArg(const char *fileName, uint32_t& len, uint32_t maxLen)
1415
0
{
1416
0
    FILE *file = NULL;
1417
0
    uint8_t *fileData = NULL;
1418
0
    long fileLen;
1419
0
    size_t fileStatus;
1420
1421
0
    file = fopen(fileName, "r");
1422
0
    if (file == NULL)
1423
0
    {
1424
0
        printf("Unable to open %s\n%s\n", fileName, strerror(errno));
1425
0
        return NULL;
1426
0
    }
1427
1428
0
    fseek(file, 0, SEEK_END);
1429
0
    fileLen = ftell(file);
1430
0
    fseek(file, 0, SEEK_SET);
1431
0
    if (ferror(file))
1432
0
    {
1433
0
        printf("Unable to read %s\n%s\n", fileName, strerror(errno));
1434
0
        fclose(file);
1435
0
        return NULL;
1436
0
    }
1437
1438
0
    len = (uint32_t) fileLen;
1439
0
    if (len > maxLen)
1440
0
    {
1441
0
        printf("File too big: %s\n", fileName);
1442
0
        fclose(file);
1443
0
        return NULL;
1444
0
    }
1445
1446
0
    fileData = (uint8_t *)malloc((size_t)len);
1447
0
    if (fileData == NULL)
1448
0
    {
1449
0
        printf("Out of memory reading %s\n", fileName);
1450
0
        fclose(file);
1451
0
        return NULL;
1452
0
    }
1453
1454
0
    fileStatus = fread(fileData, 1, (size_t)len, file);
1455
1456
0
    if ((fileStatus != len) || ferror(file))
1457
0
    {
1458
0
        printf("Unable to read %s\n%s", fileName, strerror(errno));
1459
0
        fclose(file);
1460
0
        free(fileData);
1461
0
        return NULL;
1462
0
    }
1463
1464
0
    fclose(file);
1465
1466
0
    return fileData;
1467
0
}
1468
1469
void HandleMessageReceiveError(WeaveMessageLayer *msgLayer, WEAVE_ERROR err, const IPPacketInfo *pktInfo)
1470
0
{
1471
0
    const char * const default_format = "Error receiving message from %s: %s\n";
1472
1473
0
    if (pktInfo != NULL)
1474
0
    {
1475
0
        char ipAddrStr[INET6_ADDRSTRLEN];
1476
1477
0
        pktInfo->SrcAddress.ToString(ipAddrStr, sizeof(ipAddrStr));
1478
0
        if (err == WEAVE_ERROR_INVALID_DESTINATION_NODE_ID && pktInfo->DestAddress.IsMulticast())
1479
0
        {
1480
0
            printf("Ignoring multicast message from %s addressed to different node id\n", ipAddrStr);
1481
0
        }
1482
0
        else if (err == WEAVE_ERROR_INVALID_ADDRESS && pktInfo->DestAddress.IsMulticast())
1483
0
        {
1484
0
            printf("Ignoring multicast message from %s using non-local source address\n", ipAddrStr);
1485
0
        }
1486
0
        else
1487
0
        {
1488
0
            printf(default_format, ipAddrStr, ErrorStr(err));
1489
0
        }
1490
0
    }
1491
0
    else
1492
0
    {
1493
        // general, catch-all error message
1494
1495
0
        printf(default_format, "(unknown)", ErrorStr(err));
1496
0
    }
1497
0
}
1498
1499
void HandleAcceptConnectionError(WeaveMessageLayer *msgLayer, WEAVE_ERROR err)
1500
0
{
1501
0
    printf("Error accepting incoming connection: %s\n", ErrorStr(err));
1502
0
}
1503
1504
#if CONFIG_BLE_PLATFORM_BLUEZ
1505
1506
void *WeaveBleIOLoop(void *arg)
1507
0
{
1508
0
    if (!nl::Ble::Platform::BlueZ::RunBluezIOThread((nl::Ble::Platform::BlueZ::BluezPeripheralArgs *)arg))
1509
0
    {
1510
0
        exit(EXIT_FAILURE);
1511
0
    }
1512
1513
0
    return NULL;
1514
0
}
1515
#endif /* CONFIG_BLE_PLATFORM_BLUEZ */
1516
1517
void PrintStatsCounters(nl::Weave::System::Stats::count_t *counters, const char *aPrefix)
1518
0
{
1519
0
    size_t i;
1520
0
    const nl::Weave::System::Stats::Label *strings = nl::Weave::System::Stats::GetStrings();
1521
0
    const char *prefix = aPrefix ? aPrefix : "";
1522
1523
0
    for (i = 0; i < nl::Weave::System::Stats::kNumEntries; i++)
1524
0
    {
1525
0
        printf("%s%s:\t\t%" PRI_WEAVE_SYS_STATS_COUNT "\n", prefix, strings[i], counters[i]);
1526
0
    }
1527
0
}
1528
1529
bool ProcessStats(nl::Weave::System::Stats::Snapshot &aBefore, nl::Weave::System::Stats::Snapshot &aAfter, bool aPrint, const char *aPrefix)
1530
0
{
1531
0
    bool leak = false;
1532
0
    nl::Weave::System::Stats::Snapshot delta;
1533
0
    const char *prefix = aPrefix ? aPrefix : "";
1534
0
    struct timeval sleepTime;
1535
0
    uint64_t nowUsec;
1536
0
    uint64_t upperBoundUsec;
1537
1538
    // If the current snapshot shows a leak when compared to the first one,
1539
    // we service the network for a few more rounds, to give the system
1540
    // a chance to release any "delayed-release" object that might have events
1541
    // pending. There might also be one last WRM ACK in flight after the last
1542
    // message between two nodes.
1543
    // Note that the test harnesses we have been using give the process one
1544
    // second to quit after sending a SIGUSR1, so this loop needs to complete
1545
    // well before a second in case there is a leak. If the process takes too
1546
    // long to quit, the test harness usually kills it. That causes
1547
    // the output to be truncated which in turn makes the test failure harder to
1548
    // understand.
1549
    // The loop runs for 800 milliseconds in case there is an actual leak.
1550
    // Fault-injection tests can require a longer time, since sometimes an EC is
1551
    // freed only after the max number of retransmissions.
1552
    // To allow extra time in this loop, see gFaultInjectionOptions.ExtraCleanupTimeMsec.
1553
0
    sleepTime.tv_sec = 0;
1554
0
    sleepTime.tv_usec = 100000;
1555
1556
0
    nl::Weave::Stats::UpdateSnapshot(aAfter);
1557
1558
0
    nowUsec = Now();
1559
0
    upperBoundUsec = nowUsec + 800000 + (gFaultInjectionOptions.ExtraCleanupTimeMsec * 1000);
1560
1561
0
    while (Now() < upperBoundUsec)
1562
0
    {
1563
0
        leak = nl::Weave::System::Stats::Difference(delta, aAfter, aBefore);
1564
0
        if (leak == false)
1565
0
        {
1566
0
            break;
1567
0
        }
1568
1569
0
        ServiceNetwork(sleepTime);
1570
1571
0
        nl::Weave::Stats::UpdateSnapshot(aAfter);
1572
0
    }
1573
1574
0
    if (aPrint)
1575
0
    {
1576
0
        if (gFaultInjectionOptions.DebugResourceUsage)
1577
0
        {
1578
0
            printf("\n%sResources in use before:\n", prefix);
1579
0
            PrintStatsCounters(aBefore.mResourcesInUse, prefix);
1580
1581
0
            printf("\n%sResources in use after:\n", prefix);
1582
0
            PrintStatsCounters(aAfter.mResourcesInUse, prefix);
1583
0
        }
1584
1585
0
        printf("\n%sResource leak %sdetected\n", prefix, (leak ? "" : "not "));
1586
0
        if (leak)
1587
0
        {
1588
0
            printf("%sDelta resources in use:\n", prefix);
1589
0
            PrintStatsCounters(delta.mResourcesInUse, prefix);
1590
0
            printf("%sEnd of delta resources in use\n", prefix);
1591
0
        }
1592
1593
0
        if (gFaultInjectionOptions.DebugResourceUsage)
1594
0
        {
1595
0
            printf("\nHigh watermarks:\n");
1596
0
            PrintStatsCounters(aAfter.mHighWatermarks, prefix);
1597
0
        }
1598
0
    }
1599
1600
0
    return leak;
1601
0
}
1602
1603
void PrintFaultInjectionCounters(void)
1604
0
{
1605
0
    size_t i;
1606
0
    nl::FaultInjection::Identifier faultId;
1607
0
    nl::FaultInjection::GetManagerFn faultMgrTable[] = {
1608
0
        nl::Weave::FaultInjection::GetManager,
1609
0
        nl::Inet::FaultInjection::GetManager,
1610
0
        nl::Weave::System::FaultInjection::GetManager
1611
0
    };
1612
1613
0
    if (!gFaultInjectionOptions.PrintFaultCounters)
1614
0
    {
1615
0
        return;
1616
0
    }
1617
1618
0
    printf("\nFaultInjection counters:\n");
1619
0
    for (i = 0; i < sizeof(faultMgrTable) / sizeof(faultMgrTable[0]); i++)
1620
0
    {
1621
0
        nl::FaultInjection::Manager &mgr = faultMgrTable[i]();
1622
1623
0
        for (faultId = 0; faultId < mgr.GetNumFaults(); faultId++)
1624
0
        {
1625
0
            printf("%s_%s: %u\n", mgr.GetName(), mgr.GetFaultNames()[faultId],
1626
0
                    mgr.GetFaultRecords()[faultId].mNumTimesChecked);
1627
0
        }
1628
0
    }
1629
0
    printf("End of FaultInjection counters\n");
1630
1631
0
}
1632
1633
struct RestartCallbackContext {
1634
    int mArgc;
1635
    char **mArgv;
1636
};
1637
static struct RestartCallbackContext gRestartCallbackCtx;
1638
1639
static void RebootCallbackFn(void)
1640
0
{
1641
0
    char *lArgv[gRestartCallbackCtx.mArgc +2];
1642
0
    int i;
1643
0
    int j = 0;
1644
1645
0
    if (gSigusr1Received)
1646
0
    {
1647
0
        printf("** skipping restart case after SIGUSR1 **\n");
1648
0
        ExitNow();
1649
0
    }
1650
1651
0
    for (i = 0; gRestartCallbackCtx.mArgv[i] != NULL; i++)
1652
0
    {
1653
0
        if (strcmp(gRestartCallbackCtx.mArgv[i], "--faults") == 0)
1654
0
        {
1655
            // Skip the --faults argument for now
1656
0
            i++;
1657
0
            continue;
1658
0
        }
1659
0
        lArgv[j++] = gRestartCallbackCtx.mArgv[i];
1660
0
    }
1661
1662
0
    lArgv[j] = NULL;
1663
1664
0
    for (i = 0; lArgv[i] != NULL; i++)
1665
0
    {
1666
0
        printf("argv[%d]: %s\n", i, lArgv[i]);
1667
0
    }
1668
1669
    // Need to close any open file descriptor above stdin/out/err.
1670
    // There is no portable way to get the max fd number.
1671
    // Given that Weave's test apps don't open a large number of files,
1672
    // FD_SETSIZE should be a reasonable upper bound (see the documentation
1673
    // of select).
1674
0
    for (i = 3; i < FD_SETSIZE; i++)
1675
0
    {
1676
0
        close(i);
1677
0
    }
1678
1679
0
    printf("********** Restarting *********\n");
1680
0
    fflush(stdout);
1681
0
    execvp(lArgv[0], lArgv);
1682
1683
0
exit:
1684
0
    return;
1685
0
}
1686
1687
static void PostInjectionCallbackFn(nl::FaultInjection::Manager *aManager,
1688
                             nl::FaultInjection::Identifier aId,
1689
                             nl::FaultInjection::Record *aFaultRecord)
1690
0
{
1691
0
    uint16_t numargs = aFaultRecord->mNumArguments;
1692
0
    uint16_t i;
1693
1694
0
    printf("***** Injecting fault %s_%s, instance number: %u; reboot: %s",
1695
0
                            aManager->GetName(), aManager->GetFaultNames()[aId],
1696
0
                            aFaultRecord->mNumTimesChecked, aFaultRecord->mReboot ? "yes" : "no");
1697
0
    if (numargs)
1698
0
    {
1699
0
        printf(" with %u args:", numargs);
1700
1701
0
        for (i = 0; i < numargs; i++)
1702
0
        {
1703
0
            printf(" %d", aFaultRecord->mArguments[i]);
1704
0
        }
1705
0
    }
1706
1707
0
    printf("\n");
1708
0
}
1709
1710
static nl::FaultInjection::GlobalContext gFaultInjectionGlobalContext = {
1711
    {
1712
        RebootCallbackFn,
1713
        PostInjectionCallbackFn
1714
    }
1715
};
1716
1717
static nl::FaultInjection::Callback sFuzzECHeaderCb;
1718
static nl::FaultInjection::Callback sAsyncEventCb;
1719
1720
static bool PrintFaultInjectionMaxArgCbFn(nl::FaultInjection::Manager &mgr, nl::FaultInjection::Identifier aId, nl::FaultInjection::Record *aFaultRecord, void *aContext)
1721
0
{
1722
0
    const char *faultName = mgr.GetFaultNames()[aId];
1723
1724
0
    if (gFaultInjectionOptions.PrintFaultCounters && aFaultRecord->mNumArguments)
1725
0
    {
1726
0
        printf("FI_instance_params: %s_%s_s%u maxArg: %u;\n", mgr.GetName(), faultName, aFaultRecord->mNumTimesChecked,
1727
0
                aFaultRecord->mArguments[0]);
1728
0
    }
1729
1730
0
    return false;
1731
0
}
1732
1733
static bool PrintWeaveFaultInjectionMaxArgCbFn(nl::FaultInjection::Identifier aId, nl::FaultInjection::Record *aFaultRecord, void *aContext)
1734
0
{
1735
0
    nl::FaultInjection::Manager &mgr = nl::Weave::FaultInjection::GetManager();
1736
1737
0
    return PrintFaultInjectionMaxArgCbFn(mgr, aId, aFaultRecord, aContext);
1738
0
}
1739
1740
static bool PrintSystemFaultInjectionMaxArgCbFn(nl::FaultInjection::Identifier aId, nl::FaultInjection::Record *aFaultRecord, void *aContext)
1741
0
{
1742
0
    nl::FaultInjection::Manager &mgr = nl::Weave::System::FaultInjection::GetManager();
1743
1744
0
    return PrintFaultInjectionMaxArgCbFn(mgr, aId, aFaultRecord, aContext);
1745
0
}
1746
1747
void SetupFaultInjectionContext(int argc, char *argv[])
1748
0
{
1749
0
    SetupFaultInjectionContext(argc, argv, NULL, NULL);
1750
0
}
1751
1752
void SetupFaultInjectionContext(int argc, char *argv[], int32_t (*aNumEventsAvailable)(void), void (*aInjectAsyncEvents)(int32_t index))
1753
0
{
1754
0
    nl::FaultInjection::Manager &weavemgr = nl::Weave::FaultInjection::GetManager();
1755
0
    nl::FaultInjection::Manager &systemmgr = nl::Weave::System::FaultInjection::GetManager();
1756
1757
0
    gRestartCallbackCtx.mArgc = argc;
1758
0
    gRestartCallbackCtx.mArgv = argv;
1759
1760
0
    nl::FaultInjection::SetGlobalContext(&gFaultInjectionGlobalContext);
1761
1762
0
    memset(&sFuzzECHeaderCb, 0, sizeof(sFuzzECHeaderCb));
1763
0
    sFuzzECHeaderCb.mCallBackFn = PrintWeaveFaultInjectionMaxArgCbFn;
1764
0
    weavemgr.InsertCallbackAtFault(nl::Weave::FaultInjection::kFault_FuzzExchangeHeaderTx, &sFuzzECHeaderCb);
1765
1766
0
    if (aNumEventsAvailable && aInjectAsyncEvents)
1767
0
    {
1768
0
        memset(&sAsyncEventCb, 0, sizeof(sAsyncEventCb));
1769
0
        sAsyncEventCb.mCallBackFn = PrintSystemFaultInjectionMaxArgCbFn;
1770
0
        systemmgr.InsertCallbackAtFault(nl::Weave::System::FaultInjection::kFault_AsyncEvent, &sAsyncEventCb);
1771
1772
0
        nl::Weave::System::FaultInjection::SetAsyncEventCallbacks(aNumEventsAvailable, aInjectAsyncEvents);
1773
0
    }
1774
0
}
1775
1776
/**
1777
 * Process network events until a given boolean becomes true and
1778
 * a given amount of time has elapsed. Both conditions are optional.
1779
 *
1780
 * @param[in] aDone         pointer to the boolean; if NULL, the parameter is ignored.
1781
 *
1782
 * @param[in] aIntervalMs   pointer to the number of milliseconds. The function will
1783
 *                          process events until at least this number of milliseconds
1784
 *                          has elapsed. If NULL, the parameter is ignored.
1785
 */
1786
void ServiceNetworkUntil(const bool *aDone, const uint32_t *aIntervalMs)
1787
0
{
1788
0
    uint64_t startTimeMs = NowMs();
1789
0
    uint64_t elapsedMs = 0;
1790
0
    struct timeval sleepTime;
1791
1792
0
    sleepTime.tv_sec = 0;
1793
0
    sleepTime.tv_usec = 100000;
1794
1795
0
    while (((aDone != NULL) && !(*aDone)) ||
1796
0
           ((aIntervalMs != NULL) && (elapsedMs < *aIntervalMs)))
1797
0
    {
1798
0
        ServiceNetwork(sleepTime);
1799
1800
0
        elapsedMs = NowMs() - startTimeMs;
1801
0
    }
1802
0
}