1 /*
2 * Copyright (c) 2024, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <gmock/gmock.h>
30 #include <gtest/gtest.h>
31
32 #include <arpa/inet.h>
33 #include <cstring>
34 #include <fstream>
35 #include <ifaddrs.h>
36 #include <iostream>
37 #include <net/if.h>
38 #include <netinet/in.h>
39 #include <netinet/ip6.h>
40 #include <netinet/udp.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <string>
45 #include <sys/ioctl.h>
46 #include <sys/select.h>
47 #include <sys/socket.h>
48 #include <sys/types.h>
49 #include <vector>
50
51 #ifdef __linux__
52 #include <linux/if_link.h>
53 #endif
54
55 #include <openthread/ip6.h>
56
57 #include "common/code_utils.hpp"
58 #include "common/mainloop.hpp"
59 #include "common/types.hpp"
60 #include "host/posix/netif.hpp"
61 #include "utils/socket_utils.hpp"
62
63 // Only Test on linux platform for now.
64 #ifdef __linux__
65
66 static constexpr size_t kMaxIp6Size = 1280;
67
GetAllIp6Addrs(const char * aInterfaceName)68 std::vector<std::string> GetAllIp6Addrs(const char *aInterfaceName)
69 {
70 struct ifaddrs *ifaddr, *ifa;
71 int family;
72 std::vector<std::string> ip6Addrs;
73
74 if (getifaddrs(&ifaddr) == -1)
75 {
76 perror("getifaddrs");
77 exit(EXIT_FAILURE);
78 }
79
80 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
81 {
82 if (ifa->ifa_addr == NULL)
83 {
84 continue;
85 }
86
87 family = ifa->ifa_addr->sa_family;
88 if (family == AF_INET6 && strcmp(ifa->ifa_name, aInterfaceName) == 0)
89 {
90 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)ifa->ifa_addr;
91 char addrstr[INET6_ADDRSTRLEN];
92 if (inet_ntop(AF_INET6, &(in6->sin6_addr), addrstr, sizeof(addrstr)) == NULL)
93 {
94 perror("inet_ntop");
95 exit(EXIT_FAILURE);
96 }
97
98 ip6Addrs.emplace_back(addrstr);
99 }
100 }
101
102 freeifaddrs(ifaddr);
103
104 return ip6Addrs;
105 }
106
ParseHex(char * aStr,unsigned char * aAddr)107 static int ParseHex(char *aStr, unsigned char *aAddr)
108 {
109 int len = 0;
110
111 while (*aStr)
112 {
113 int tmp;
114 if (aStr[1] == 0)
115 {
116 return -1;
117 }
118 if (sscanf(aStr, "%02x", &tmp) != 1)
119 {
120 return -1;
121 }
122 aAddr[len] = tmp;
123 len++;
124 aStr += 2;
125 }
126
127 return len;
128 }
129
GetAllIp6MulAddrs(const char * aInterfaceName)130 std::vector<std::string> GetAllIp6MulAddrs(const char *aInterfaceName)
131 {
132 const char *kPathIgmp6 = "/proc/net/igmp6";
133 std::string line;
134 std::vector<std::string> ip6MulAddrs;
135
136 std::ifstream file(kPathIgmp6);
137 if (!file.is_open())
138 {
139 perror("Cannot open IGMP6 file");
140 exit(EXIT_FAILURE);
141 }
142
143 while (std::getline(file, line))
144 {
145 char interfaceName[256] = {0};
146 char hexa[256] = {0};
147 int index;
148 int users;
149 unsigned char addr[16];
150
151 sscanf(line.c_str(), "%d%s%s%d", &index, interfaceName, hexa, &users);
152 if (strcmp(interfaceName, aInterfaceName) == 0)
153 {
154 char addrStr[INET6_ADDRSTRLEN];
155 ParseHex(hexa, addr);
156 if (inet_ntop(AF_INET6, addr, addrStr, sizeof(addrStr)) == NULL)
157 {
158 perror("inet_ntop");
159 exit(EXIT_FAILURE);
160 }
161 ip6MulAddrs.emplace_back(addrStr);
162 }
163 }
164
165 file.close();
166
167 return ip6MulAddrs;
168 }
169
170 static otbr::Netif::Dependencies sDefaultNetifDependencies;
171
TEST(Netif,WpanInitWithFullInterfaceName)172 TEST(Netif, WpanInitWithFullInterfaceName)
173 {
174 const char *wpan = "wpan0";
175 int sockfd;
176 struct ifreq ifr;
177
178 otbr::Netif netif(sDefaultNetifDependencies);
179 EXPECT_EQ(netif.Init(wpan), OT_ERROR_NONE);
180
181 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
182 if (sockfd < 0)
183 {
184 FAIL() << "Error creating socket: " << std::strerror(errno);
185 }
186
187 memset(&ifr, 0, sizeof(ifr));
188 strncpy(ifr.ifr_name, wpan, IFNAMSIZ - 1);
189
190 EXPECT_GE(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << wpan << "' not found";
191
192 netif.Deinit();
193 }
194
TEST(Netif,WpanInitWithFormatInterfaceName)195 TEST(Netif, WpanInitWithFormatInterfaceName)
196 {
197 const char *wpan = "tun%d";
198 const char *if_name = "tun0";
199 int sockfd;
200 struct ifreq ifr;
201
202 otbr::Netif netif(sDefaultNetifDependencies);
203 EXPECT_EQ(netif.Init(wpan), OT_ERROR_NONE);
204
205 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
206 if (sockfd < 0)
207 {
208 FAIL() << "Error creating socket: " << std::strerror(errno);
209 }
210
211 memset(&ifr, 0, sizeof(ifr));
212 strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
213
214 EXPECT_GE(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << if_name << "' not found";
215
216 netif.Deinit();
217 }
218
TEST(Netif,WpanInitWithEmptyInterfaceName)219 TEST(Netif, WpanInitWithEmptyInterfaceName)
220 {
221 const char *if_name = "wpan0";
222 int sockfd;
223 struct ifreq ifr;
224
225 otbr::Netif netif(sDefaultNetifDependencies);
226 EXPECT_EQ(netif.Init(""), OT_ERROR_NONE);
227
228 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
229 if (sockfd < 0)
230 {
231 FAIL() << "Error creating socket: " << std::strerror(errno);
232 }
233
234 memset(&ifr, 0, sizeof(ifr));
235 strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
236
237 EXPECT_GE(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << if_name << "' not found";
238
239 netif.Deinit();
240 }
241
TEST(Netif,WpanInitWithInvalidInterfaceName)242 TEST(Netif, WpanInitWithInvalidInterfaceName)
243 {
244 const char *invalid_netif_name = "invalid_netif_name";
245
246 otbr::Netif netif(sDefaultNetifDependencies);
247 EXPECT_EQ(netif.Init(invalid_netif_name), OTBR_ERROR_INVALID_ARGS);
248 }
249
TEST(Netif,WpanMtuSize)250 TEST(Netif, WpanMtuSize)
251 {
252 const char *wpan = "wpan0";
253 int sockfd;
254 struct ifreq ifr;
255
256 otbr::Netif netif(sDefaultNetifDependencies);
257 EXPECT_EQ(netif.Init(wpan), OT_ERROR_NONE);
258
259 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
260 if (sockfd < 0)
261 {
262 FAIL() << "Error creating socket: " << std::strerror(errno);
263 }
264
265 memset(&ifr, 0, sizeof(ifr));
266 strncpy(ifr.ifr_name, wpan, IFNAMSIZ - 1);
267 EXPECT_GE(ioctl(sockfd, SIOCGIFMTU, &ifr), 0) << "Error getting MTU for '" << wpan << "': " << std::strerror(errno);
268 EXPECT_EQ(ifr.ifr_mtu, kMaxIp6Size) << "MTU isn't set correctly";
269
270 netif.Deinit();
271 }
272
TEST(Netif,WpanDeinit)273 TEST(Netif, WpanDeinit)
274 {
275 const char *wpan = "wpan0";
276 int sockfd;
277 struct ifreq ifr;
278
279 otbr::Netif netif(sDefaultNetifDependencies);
280 EXPECT_EQ(netif.Init(wpan), OT_ERROR_NONE);
281
282 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
283 if (sockfd < 0)
284 {
285 FAIL() << "Error creating socket: " << std::strerror(errno);
286 }
287
288 memset(&ifr, 0, sizeof(ifr));
289 strncpy(ifr.ifr_name, wpan, IFNAMSIZ - 1);
290 EXPECT_GE(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << wpan << "' not found";
291
292 netif.Deinit();
293 EXPECT_LT(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << wpan << "' isn't shutdown";
294 }
295
TEST(Netif,WpanAddrGenMode)296 TEST(Netif, WpanAddrGenMode)
297 {
298 otbr::Netif netif(sDefaultNetifDependencies);
299 EXPECT_EQ(netif.Init("wpan0"), OT_ERROR_NONE);
300
301 std::fstream file("/proc/sys/net/ipv6/conf/wpan0/addr_gen_mode", std::ios::in);
302 if (!file.is_open())
303 {
304 FAIL() << "wpan0 interface doesn't exist!";
305 }
306 std::string fileContents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
307
308 EXPECT_EQ(std::stoi(fileContents), IN6_ADDR_GEN_MODE_NONE);
309
310 netif.Deinit();
311 }
312
TEST(Netif,WpanIfHasCorrectUnicastAddresses_AfterUpdatingUnicastAddresses)313 TEST(Netif, WpanIfHasCorrectUnicastAddresses_AfterUpdatingUnicastAddresses)
314 {
315 const char *wpan = "wpan0";
316
317 const otIp6Address kLl = {
318 {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x14, 0x03, 0x32, 0x4c, 0xc2, 0xf8, 0xd0}};
319 const otIp6Address kMlEid = {
320 {0xfd, 0x0d, 0x07, 0xfc, 0xa1, 0xb9, 0xf0, 0x50, 0x03, 0xf1, 0x47, 0xce, 0x85, 0xd3, 0x07, 0x7f}};
321 const otIp6Address kMlRloc = {
322 {0xfd, 0x0d, 0x07, 0xfc, 0xa1, 0xb9, 0xf0, 0x50, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0xb8, 0x00}};
323 const otIp6Address kMlAloc = {
324 {0xfd, 0x0d, 0x07, 0xfc, 0xa1, 0xb9, 0xf0, 0x50, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0xfc, 0x00}};
325
326 const char *kLlStr = "fe80::8014:332:4cc2:f8d0";
327 const char *kMlEidStr = "fd0d:7fc:a1b9:f050:3f1:47ce:85d3:77f";
328 const char *kMlRlocStr = "fd0d:7fc:a1b9:f050:0:ff:fe00:b800";
329 const char *kMlAlocStr = "fd0d:7fc:a1b9:f050:0:ff:fe00:fc00";
330
331 otbr::Netif netif(sDefaultNetifDependencies);
332 EXPECT_EQ(netif.Init(wpan), OT_ERROR_NONE);
333
334 otbr::Ip6AddressInfo testArray1[] = {
335 {kLl, 64, 0, 1, 0},
336 {kMlEid, 64, 0, 1, 1},
337 {kMlRloc, 64, 0, 1, 1},
338 };
339 std::vector<otbr::Ip6AddressInfo> testVec1(testArray1,
340 testArray1 + sizeof(testArray1) / sizeof(otbr::Ip6AddressInfo));
341 netif.UpdateIp6UnicastAddresses(testVec1);
342 std::vector<std::string> wpan_addrs = GetAllIp6Addrs(wpan);
343 EXPECT_EQ(wpan_addrs.size(), 3);
344 EXPECT_THAT(wpan_addrs, ::testing::Contains(kLlStr));
345 EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlEidStr));
346 EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlRlocStr));
347
348 otbr::Ip6AddressInfo testArray2[] = {
349 {kLl, 64, 0, 1, 0},
350 {kMlEid, 64, 0, 1, 1},
351 {kMlRloc, 64, 0, 1, 1},
352 {kMlAloc, 64, 0, 1, 1},
353 };
354 std::vector<otbr::Ip6AddressInfo> testVec2(testArray2,
355 testArray2 + sizeof(testArray2) / sizeof(otbr::Ip6AddressInfo));
356 netif.UpdateIp6UnicastAddresses(testVec2);
357 wpan_addrs = GetAllIp6Addrs(wpan);
358 EXPECT_EQ(wpan_addrs.size(), 4);
359 EXPECT_THAT(wpan_addrs, ::testing::Contains(kLlStr));
360 EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlEidStr));
361 EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlRlocStr));
362 EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlAlocStr));
363
364 std::vector<otbr::Ip6AddressInfo> testVec3;
365 netif.UpdateIp6UnicastAddresses(testVec3);
366 wpan_addrs = GetAllIp6Addrs(wpan);
367 EXPECT_EQ(wpan_addrs.size(), 0);
368
369 netif.Deinit();
370 }
371
TEST(Netif,WpanIfHasCorrectMulticastAddresses_AfterUpdatingMulticastAddresses)372 TEST(Netif, WpanIfHasCorrectMulticastAddresses_AfterUpdatingMulticastAddresses)
373 {
374 const char *wpan = "wpan0";
375 otbr::Netif netif(sDefaultNetifDependencies);
376 EXPECT_EQ(netif.Init(wpan), OT_ERROR_NONE);
377
378 otbr::Ip6Address kDefaultMulAddr1 = {
379 {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};
380 const char *kDefaultMulAddr1Str = "ff01::1";
381 const char *kDefaultMulAddr2Str = "ff02::1";
382 const char *kDefaultMulAddr3Str = "ff02::2";
383 const char *kDefaultMulAddr4Str = "ff02::16";
384
385 otbr::Ip6Address kMulAddr1 = {
386 {0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc}};
387 otbr::Ip6Address kMulAddr2 = {
388 {0xff, 0x32, 0x00, 0x40, 0xfd, 0x0d, 0x07, 0xfc, 0xa1, 0xb9, 0xf0, 0x50, 0x00, 0x00, 0x00, 0x01}};
389 const char *kMulAddr1Str = "ff03::fc";
390 const char *kMulAddr2Str = "ff32:40:fd0d:7fc:a1b9:f050:0:1";
391
392 otbr::Ip6Address testArray1[] = {
393 kMulAddr1,
394 };
395 std::vector<otbr::Ip6Address> testVec1(testArray1, testArray1 + sizeof(testArray1) / sizeof(otbr::Ip6Address));
396 netif.UpdateIp6MulticastAddresses(testVec1);
397 std::vector<std::string> wpanMulAddrs = GetAllIp6MulAddrs(wpan);
398 EXPECT_EQ(wpanMulAddrs.size(), 5);
399 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kMulAddr1Str));
400 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr1Str));
401 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr2Str));
402 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr3Str));
403 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr4Str));
404
405 otbr::Ip6Address testArray2[] = {kMulAddr1, kMulAddr2};
406 std::vector<otbr::Ip6Address> testVec2(testArray2, testArray2 + sizeof(testArray2) / sizeof(otbr::Ip6Address));
407 netif.UpdateIp6MulticastAddresses(testVec2);
408 wpanMulAddrs = GetAllIp6MulAddrs(wpan);
409 EXPECT_EQ(wpanMulAddrs.size(), 6);
410 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kMulAddr1Str));
411 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kMulAddr2Str));
412 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr1Str));
413 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr2Str));
414 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr3Str));
415 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr4Str));
416
417 otbr::Ip6Address testArray3[] = {kDefaultMulAddr1};
418 std::vector<otbr::Ip6Address> testVec3(testArray3, testArray3 + sizeof(testArray3) / sizeof(otbr::Ip6Address));
419 netif.UpdateIp6MulticastAddresses(testVec3);
420 wpanMulAddrs = GetAllIp6MulAddrs(wpan);
421 EXPECT_EQ(wpanMulAddrs.size(), 4);
422 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr1Str));
423 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr2Str));
424 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr3Str));
425 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr4Str));
426
427 std::vector<otbr::Ip6Address> empty;
428 netif.UpdateIp6MulticastAddresses(empty);
429 wpanMulAddrs = GetAllIp6MulAddrs(wpan);
430 EXPECT_EQ(wpanMulAddrs.size(), 4);
431 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr1Str));
432 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr2Str));
433 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr3Str));
434 EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr4Str));
435
436 netif.Deinit();
437 }
438
TEST(Netif,WpanIfStateChangesCorrectly_AfterSettingNetifState)439 TEST(Netif, WpanIfStateChangesCorrectly_AfterSettingNetifState)
440 {
441 otbr::Netif netif(sDefaultNetifDependencies);
442 const char *wpan = "wpan0";
443 EXPECT_EQ(netif.Init(wpan), OTBR_ERROR_NONE);
444
445 int fd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
446 if (fd < 0)
447 {
448 perror("Failed to create test socket");
449 exit(EXIT_FAILURE);
450 }
451
452 struct ifreq ifr;
453 memset(&ifr, 0, sizeof(ifr));
454 strncpy(ifr.ifr_name, wpan, IFNAMSIZ - 1);
455
456 netif.SetNetifState(true);
457 ioctl(fd, SIOCGIFFLAGS, &ifr);
458 EXPECT_EQ(ifr.ifr_flags & IFF_UP, IFF_UP);
459
460 netif.SetNetifState(false);
461 ioctl(fd, SIOCGIFFLAGS, &ifr);
462 EXPECT_EQ(ifr.ifr_flags & IFF_UP, 0);
463
464 netif.Deinit();
465 }
466
TEST(Netif,WpanIfRecvIp6PacketCorrectly_AfterReceivingFromNetif)467 TEST(Netif, WpanIfRecvIp6PacketCorrectly_AfterReceivingFromNetif)
468 {
469 otbr::Netif netif(sDefaultNetifDependencies);
470 EXPECT_EQ(netif.Init("wpan0"), OTBR_ERROR_NONE);
471
472 const otIp6Address kOmr = {
473 {0xfd, 0x2a, 0xc3, 0x0c, 0x87, 0xd3, 0x00, 0x01, 0xed, 0x1c, 0x0c, 0x91, 0xcc, 0xb6, 0x57, 0x8b}};
474 std::vector<otbr::Ip6AddressInfo> addrs = {
475 {kOmr, 64, 0, 1, 0},
476 };
477 netif.UpdateIp6UnicastAddresses(addrs);
478 netif.SetNetifState(true);
479
480 // Receive UDP packets on wpan address with specified port.
481 int sockFd;
482 const uint16_t port = 12345;
483 struct sockaddr_in6 listenAddr;
484 const char *listenIp = "fd2a:c30c:87d3:1:ed1c:c91:ccb6:578b";
485 uint8_t recvBuf[kMaxIp6Size];
486
487 if ((sockFd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
488 {
489 perror("socket creation failed");
490 exit(EXIT_FAILURE);
491 }
492
493 memset(&listenAddr, 0, sizeof(listenAddr));
494 listenAddr.sin6_family = AF_INET6;
495 listenAddr.sin6_port = htons(port);
496 inet_pton(AF_INET6, listenIp, &(listenAddr.sin6_addr));
497
498 if (bind(sockFd, (const struct sockaddr *)&listenAddr, sizeof(listenAddr)) < 0)
499 {
500 perror("bind failed");
501 exit(EXIT_FAILURE);
502 }
503
504 // Udp Packet
505 // Ip6 source: fd2a:c30c:87d3:1:ed1c:c91:ccb6:578a
506 // Ip6 destination: fd2a:c30c:87d3:1:ed1c:c91:ccb6:578b
507 // Udp destination port: 12345
508 // Udp payload: "Hello Otbr Netif!"
509 const uint8_t udpPacket[] = {0x60, 0x0e, 0xea, 0x69, 0x00, 0x19, 0x11, 0x40, 0xfd, 0x2a, 0xc3, 0x0c, 0x87,
510 0xd3, 0x00, 0x01, 0xed, 0x1c, 0x0c, 0x91, 0xcc, 0xb6, 0x57, 0x8a, 0xfd, 0x2a,
511 0xc3, 0x0c, 0x87, 0xd3, 0x00, 0x01, 0xed, 0x1c, 0x0c, 0x91, 0xcc, 0xb6, 0x57,
512 0x8b, 0xe7, 0x08, 0x30, 0x39, 0x00, 0x19, 0x36, 0x81, 0x48, 0x65, 0x6c, 0x6c,
513 0x6f, 0x20, 0x4f, 0x74, 0x62, 0x72, 0x20, 0x4e, 0x65, 0x74, 0x69, 0x66, 0x21};
514 netif.Ip6Receive(udpPacket, sizeof(udpPacket));
515
516 socklen_t len = sizeof(listenAddr);
517 int n = recvfrom(sockFd, (char *)recvBuf, kMaxIp6Size, MSG_WAITALL, (struct sockaddr *)&listenAddr, &len);
518 std::string udpPayload(reinterpret_cast<const char *>(recvBuf), n);
519 EXPECT_EQ(udpPayload, "Hello Otbr Netif!");
520
521 close(sockFd);
522 netif.Deinit();
523 }
524
525 class NetifDependencyTestIp6Send : public otbr::Netif::Dependencies
526 {
527 public:
NetifDependencyTestIp6Send(bool & aReceived,std::string & aReceivedPayload)528 NetifDependencyTestIp6Send(bool &aReceived, std::string &aReceivedPayload)
529 : mReceived(aReceived)
530 , mReceivedPayload(aReceivedPayload)
531 {
532 }
533
Ip6Send(const uint8_t * aData,uint16_t aLength)534 otbrError Ip6Send(const uint8_t *aData, uint16_t aLength) override
535 {
536 const ip6_hdr *ipv6_header = reinterpret_cast<const ip6_hdr *>(aData);
537 if (ipv6_header->ip6_nxt == IPPROTO_UDP)
538 {
539 const uint8_t *udpPayload = aData + aLength - ntohs(ipv6_header->ip6_plen) + sizeof(udphdr);
540 uint16_t udpPayloadLen = ntohs(ipv6_header->ip6_plen) - sizeof(udphdr);
541 mReceivedPayload = std::string(reinterpret_cast<const char *>(udpPayload), udpPayloadLen);
542
543 mReceived = true;
544 }
545
546 return OTBR_ERROR_NONE;
547 }
548
549 bool &mReceived;
550 std::string &mReceivedPayload;
551 };
552
TEST(Netif,WpanIfSendIp6PacketCorrectly_AfterReceivingOnIf)553 TEST(Netif, WpanIfSendIp6PacketCorrectly_AfterReceivingOnIf)
554 {
555 bool received = false;
556 std::string receivedPayload;
557 NetifDependencyTestIp6Send netifDependency(received, receivedPayload);
558 const char *hello = "Hello Otbr Netif!";
559
560 otbr::Netif netif(netifDependency);
561 EXPECT_EQ(netif.Init("wpan0"), OT_ERROR_NONE);
562
563 // OMR Prefix: fd76:a5d1:fcb0:1707::/64
564 const otIp6Address kOmr = {
565 {0xfd, 0x76, 0xa5, 0xd1, 0xfc, 0xb0, 0x17, 0x07, 0xf3, 0xc7, 0xd8, 0x8c, 0xef, 0xd1, 0x24, 0xa9}};
566 std::vector<otbr::Ip6AddressInfo> addrs = {
567 {kOmr, 64, 0, 1, 0},
568 };
569 netif.UpdateIp6UnicastAddresses(addrs);
570 netif.SetNetifState(true);
571
572 // Send a UDP packet destined to an address with OMR prefix.
573 {
574 int sockFd;
575 const uint16_t destPort = 12345;
576 struct sockaddr_in6 destAddr;
577 const char *destIp = "fd76:a5d1:fcb0:1707:3f1:47ce:85d3:77f";
578
579 if ((sockFd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
580 {
581 perror("socket creation failed");
582 exit(EXIT_FAILURE);
583 }
584
585 memset(&destAddr, 0, sizeof(destAddr));
586 destAddr.sin6_family = AF_INET6;
587 destAddr.sin6_port = htons(destPort);
588 inet_pton(AF_INET6, destIp, &(destAddr.sin6_addr));
589
590 if (sendto(sockFd, hello, strlen(hello), MSG_CONFIRM, (const struct sockaddr *)&destAddr, sizeof(destAddr)) < 0)
591 {
592 FAIL() << "Failed to send UDP packet through WPAN interface";
593 }
594 close(sockFd);
595 }
596
597 otbr::MainloopContext context;
598 while (!received)
599 {
600 context.mMaxFd = -1;
601 context.mTimeout = {100, 0};
602 FD_ZERO(&context.mReadFdSet);
603 FD_ZERO(&context.mWriteFdSet);
604 FD_ZERO(&context.mErrorFdSet);
605
606 netif.UpdateFdSet(&context);
607 int rval = select(context.mMaxFd + 1, &context.mReadFdSet, &context.mWriteFdSet, &context.mErrorFdSet,
608 &context.mTimeout);
609 if (rval < 0)
610 {
611 perror("select failed");
612 exit(EXIT_FAILURE);
613 }
614 netif.Process(&context);
615 }
616
617 EXPECT_STREQ(receivedPayload.c_str(), hello);
618
619 netif.Deinit();
620 }
621
622 class NetifDependencyTestMulSub : public otbr::Netif::Dependencies
623 {
624 public:
NetifDependencyTestMulSub(bool & aReceived,otIp6Address & aMulAddr,bool & aIsAdded)625 NetifDependencyTestMulSub(bool &aReceived, otIp6Address &aMulAddr, bool &aIsAdded)
626 : mReceived(aReceived)
627 , mMulAddr(aMulAddr)
628 , mIsAdded(aIsAdded)
629 {
630 }
631
Ip6MulAddrUpdateSubscription(const otIp6Address & aAddress,bool aIsAdded)632 otbrError Ip6MulAddrUpdateSubscription(const otIp6Address &aAddress, bool aIsAdded) override
633 {
634 mMulAddr = aAddress;
635 mIsAdded = aIsAdded;
636 mReceived = true;
637 return OTBR_ERROR_NONE;
638 }
639
640 bool &mReceived;
641 otIp6Address &mMulAddr;
642 bool &mIsAdded;
643 };
644
TEST(Netif,WpanIfUpdateMulAddrSubscription_AfterAppJoiningMulGrp)645 TEST(Netif, WpanIfUpdateMulAddrSubscription_AfterAppJoiningMulGrp)
646 {
647 bool received = false;
648 otIp6Address subscribedMulAddr;
649 bool isAdded = false;
650 NetifDependencyTestMulSub dependency(received, subscribedMulAddr, isAdded);
651 const char *multicastGroup = "ff99::1";
652 const char *wpan = "wpan0";
653 int sockFd;
654 otbr::Netif netif(dependency);
655 const otIp6Address expectedMulAddr = {0xff, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
657
658 EXPECT_EQ(netif.Init("wpan0"), OT_ERROR_NONE);
659
660 const otIp6Address kLl = {
661 {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x14, 0x03, 0x32, 0x4c, 0xc2, 0xf8, 0xd0}};
662 std::vector<otbr::Ip6AddressInfo> addrs = {
663 {kLl, 64, 0, 1, 0},
664 };
665 netif.UpdateIp6UnicastAddresses(addrs);
666 netif.SetNetifState(true);
667
668 {
669 struct ipv6_mreq mreq;
670 struct sockaddr_in6 addr;
671
672 if ((sockFd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
673 {
674 perror("socket creation failed");
675 exit(EXIT_FAILURE);
676 }
677
678 memset(&addr, 0, sizeof(addr));
679 addr.sin6_family = AF_INET6;
680 addr.sin6_addr = in6addr_any;
681 addr.sin6_port = htons(9999);
682
683 if (bind(sockFd, (const struct sockaddr *)&addr, sizeof(addr)) < 0)
684 {
685 perror("bind failed");
686 exit(EXIT_FAILURE);
687 }
688
689 inet_pton(AF_INET6, multicastGroup, &(mreq.ipv6mr_multiaddr));
690 mreq.ipv6mr_interface = if_nametoindex(wpan);
691
692 if (setsockopt(sockFd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)
693 {
694 perror("Error joining multicast group");
695 exit(EXIT_FAILURE);
696 }
697 }
698
699 otbr::MainloopContext context;
700 while (!received)
701 {
702 context.mMaxFd = -1;
703 context.mTimeout = {100, 0};
704 FD_ZERO(&context.mReadFdSet);
705 FD_ZERO(&context.mWriteFdSet);
706 FD_ZERO(&context.mErrorFdSet);
707
708 netif.UpdateFdSet(&context);
709 int rval = select(context.mMaxFd + 1, &context.mReadFdSet, &context.mWriteFdSet, &context.mErrorFdSet,
710 &context.mTimeout);
711 if (rval < 0)
712 {
713 perror("select failed");
714 exit(EXIT_FAILURE);
715 }
716 netif.Process(&context);
717 }
718
719 EXPECT_EQ(otbr::Ip6Address(subscribedMulAddr), otbr::Ip6Address(expectedMulAddr));
720 EXPECT_EQ(isAdded, true);
721 close(sockFd);
722 netif.Deinit();
723 }
724
725 #endif // __linux__
726