• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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