/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 | } |