xref: /aosp_15_r20/external/ot-br-posix/tests/gtest/test_netif.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
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 "ncp/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 
Ip6SendEmptyImpl(const uint8_t * aData,uint16_t aLength)170 otbrError Ip6SendEmptyImpl(const uint8_t *aData, uint16_t aLength)
171 {
172     OTBR_UNUSED_VARIABLE(aData);
173     OTBR_UNUSED_VARIABLE(aLength);
174     return OTBR_ERROR_NONE;
175 }
176 
TEST(Netif,WpanInitWithFullInterfaceName)177 TEST(Netif, WpanInitWithFullInterfaceName)
178 {
179     const char  *wpan = "wpan0";
180     int          sockfd;
181     struct ifreq ifr;
182 
183     otbr::Netif netif;
184     EXPECT_EQ(netif.Init(wpan, Ip6SendEmptyImpl), OT_ERROR_NONE);
185 
186     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
187     if (sockfd < 0)
188     {
189         FAIL() << "Error creating socket: " << std::strerror(errno);
190     }
191 
192     memset(&ifr, 0, sizeof(ifr));
193     strncpy(ifr.ifr_name, wpan, IFNAMSIZ - 1);
194 
195     EXPECT_GE(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << wpan << "' not found";
196 
197     netif.Deinit();
198 }
199 
TEST(Netif,WpanInitWithFormatInterfaceName)200 TEST(Netif, WpanInitWithFormatInterfaceName)
201 {
202     const char  *wpan    = "tun%d";
203     const char  *if_name = "tun0";
204     int          sockfd;
205     struct ifreq ifr;
206 
207     otbr::Netif netif;
208     EXPECT_EQ(netif.Init(wpan, Ip6SendEmptyImpl), OT_ERROR_NONE);
209 
210     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
211     if (sockfd < 0)
212     {
213         FAIL() << "Error creating socket: " << std::strerror(errno);
214     }
215 
216     memset(&ifr, 0, sizeof(ifr));
217     strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
218 
219     EXPECT_GE(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << if_name << "' not found";
220 
221     netif.Deinit();
222 }
223 
TEST(Netif,WpanInitWithEmptyInterfaceName)224 TEST(Netif, WpanInitWithEmptyInterfaceName)
225 {
226     const char  *if_name = "wpan0";
227     int          sockfd;
228     struct ifreq ifr;
229 
230     otbr::Netif netif;
231     EXPECT_EQ(netif.Init("", Ip6SendEmptyImpl), OT_ERROR_NONE);
232 
233     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
234     if (sockfd < 0)
235     {
236         FAIL() << "Error creating socket: " << std::strerror(errno);
237     }
238 
239     memset(&ifr, 0, sizeof(ifr));
240     strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
241 
242     EXPECT_GE(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << if_name << "' not found";
243 
244     netif.Deinit();
245 }
246 
TEST(Netif,WpanInitWithInvalidInterfaceName)247 TEST(Netif, WpanInitWithInvalidInterfaceName)
248 {
249     const char *invalid_netif_name = "invalid_netif_name";
250 
251     otbr::Netif netif;
252     EXPECT_EQ(netif.Init(invalid_netif_name, Ip6SendEmptyImpl), OTBR_ERROR_INVALID_ARGS);
253 }
254 
TEST(Netif,WpanMtuSize)255 TEST(Netif, WpanMtuSize)
256 {
257     const char  *wpan = "wpan0";
258     int          sockfd;
259     struct ifreq ifr;
260 
261     otbr::Netif netif;
262     EXPECT_EQ(netif.Init(wpan, Ip6SendEmptyImpl), OT_ERROR_NONE);
263 
264     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
265     if (sockfd < 0)
266     {
267         FAIL() << "Error creating socket: " << std::strerror(errno);
268     }
269 
270     memset(&ifr, 0, sizeof(ifr));
271     strncpy(ifr.ifr_name, wpan, IFNAMSIZ - 1);
272     EXPECT_GE(ioctl(sockfd, SIOCGIFMTU, &ifr), 0) << "Error getting MTU for '" << wpan << "': " << std::strerror(errno);
273     EXPECT_EQ(ifr.ifr_mtu, kMaxIp6Size) << "MTU isn't set correctly";
274 
275     netif.Deinit();
276 }
277 
TEST(Netif,WpanDeinit)278 TEST(Netif, WpanDeinit)
279 {
280     const char  *wpan = "wpan0";
281     int          sockfd;
282     struct ifreq ifr;
283 
284     otbr::Netif netif;
285     EXPECT_EQ(netif.Init(wpan, Ip6SendEmptyImpl), OT_ERROR_NONE);
286 
287     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
288     if (sockfd < 0)
289     {
290         FAIL() << "Error creating socket: " << std::strerror(errno);
291     }
292 
293     memset(&ifr, 0, sizeof(ifr));
294     strncpy(ifr.ifr_name, wpan, IFNAMSIZ - 1);
295     EXPECT_GE(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << wpan << "' not found";
296 
297     netif.Deinit();
298     EXPECT_LT(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << wpan << "' isn't shutdown";
299 }
300 
TEST(Netif,WpanAddrGenMode)301 TEST(Netif, WpanAddrGenMode)
302 {
303     otbr::Netif netif;
304     EXPECT_EQ(netif.Init("wpan0", Ip6SendEmptyImpl), OT_ERROR_NONE);
305 
306     std::fstream file("/proc/sys/net/ipv6/conf/wpan0/addr_gen_mode", std::ios::in);
307     if (!file.is_open())
308     {
309         FAIL() << "wpan0 interface doesn't exist!";
310     }
311     std::string fileContents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
312 
313     EXPECT_EQ(std::stoi(fileContents), IN6_ADDR_GEN_MODE_NONE);
314 
315     netif.Deinit();
316 }
317 
TEST(Netif,WpanIfHasCorrectUnicastAddresses_AfterUpdatingUnicastAddresses)318 TEST(Netif, WpanIfHasCorrectUnicastAddresses_AfterUpdatingUnicastAddresses)
319 {
320     const char *wpan = "wpan0";
321 
322     const otIp6Address kLl = {
323         {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x14, 0x03, 0x32, 0x4c, 0xc2, 0xf8, 0xd0}};
324     const otIp6Address kMlEid = {
325         {0xfd, 0x0d, 0x07, 0xfc, 0xa1, 0xb9, 0xf0, 0x50, 0x03, 0xf1, 0x47, 0xce, 0x85, 0xd3, 0x07, 0x7f}};
326     const otIp6Address kMlRloc = {
327         {0xfd, 0x0d, 0x07, 0xfc, 0xa1, 0xb9, 0xf0, 0x50, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0xb8, 0x00}};
328     const otIp6Address kMlAloc = {
329         {0xfd, 0x0d, 0x07, 0xfc, 0xa1, 0xb9, 0xf0, 0x50, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0xfc, 0x00}};
330 
331     const char *kLlStr     = "fe80::8014:332:4cc2:f8d0";
332     const char *kMlEidStr  = "fd0d:7fc:a1b9:f050:3f1:47ce:85d3:77f";
333     const char *kMlRlocStr = "fd0d:7fc:a1b9:f050:0:ff:fe00:b800";
334     const char *kMlAlocStr = "fd0d:7fc:a1b9:f050:0:ff:fe00:fc00";
335 
336     otbr::Netif netif;
337     EXPECT_EQ(netif.Init(wpan, Ip6SendEmptyImpl), OT_ERROR_NONE);
338 
339     otbr::Ip6AddressInfo testArray1[] = {
340         {kLl, 64, 0, 1, 0},
341         {kMlEid, 64, 0, 1, 1},
342         {kMlRloc, 64, 0, 1, 1},
343     };
344     std::vector<otbr::Ip6AddressInfo> testVec1(testArray1,
345                                                testArray1 + sizeof(testArray1) / sizeof(otbr::Ip6AddressInfo));
346     netif.UpdateIp6UnicastAddresses(testVec1);
347     std::vector<std::string> wpan_addrs = GetAllIp6Addrs(wpan);
348     EXPECT_EQ(wpan_addrs.size(), 3);
349     EXPECT_THAT(wpan_addrs, ::testing::Contains(kLlStr));
350     EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlEidStr));
351     EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlRlocStr));
352 
353     otbr::Ip6AddressInfo testArray2[] = {
354         {kLl, 64, 0, 1, 0},
355         {kMlEid, 64, 0, 1, 1},
356         {kMlRloc, 64, 0, 1, 1},
357         {kMlAloc, 64, 0, 1, 1},
358     };
359     std::vector<otbr::Ip6AddressInfo> testVec2(testArray2,
360                                                testArray2 + sizeof(testArray2) / sizeof(otbr::Ip6AddressInfo));
361     netif.UpdateIp6UnicastAddresses(testVec2);
362     wpan_addrs = GetAllIp6Addrs(wpan);
363     EXPECT_EQ(wpan_addrs.size(), 4);
364     EXPECT_THAT(wpan_addrs, ::testing::Contains(kLlStr));
365     EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlEidStr));
366     EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlRlocStr));
367     EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlAlocStr));
368 
369     std::vector<otbr::Ip6AddressInfo> testVec3;
370     netif.UpdateIp6UnicastAddresses(testVec3);
371     wpan_addrs = GetAllIp6Addrs(wpan);
372     EXPECT_EQ(wpan_addrs.size(), 0);
373 
374     netif.Deinit();
375 }
376 
TEST(Netif,WpanIfHasCorrectMulticastAddresses_AfterUpdatingMulticastAddresses)377 TEST(Netif, WpanIfHasCorrectMulticastAddresses_AfterUpdatingMulticastAddresses)
378 {
379     const char *wpan = "wpan0";
380     otbr::Netif netif;
381     EXPECT_EQ(netif.Init(wpan, Ip6SendEmptyImpl), OT_ERROR_NONE);
382 
383     otbr::Ip6Address kDefaultMulAddr1 = {
384         {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};
385     const char *kDefaultMulAddr1Str = "ff01::1";
386     const char *kDefaultMulAddr2Str = "ff02::1";
387     const char *kDefaultMulAddr3Str = "ff02::2";
388 
389     otbr::Ip6Address kMulAddr1 = {
390         {0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc}};
391     otbr::Ip6Address kMulAddr2 = {
392         {0xff, 0x32, 0x00, 0x40, 0xfd, 0x0d, 0x07, 0xfc, 0xa1, 0xb9, 0xf0, 0x50, 0x00, 0x00, 0x00, 0x01}};
393     const char *kMulAddr1Str = "ff03::fc";
394     const char *kMulAddr2Str = "ff32:40:fd0d:7fc:a1b9:f050:0:1";
395 
396     otbr::Ip6Address testArray1[] = {
397         kMulAddr1,
398     };
399     std::vector<otbr::Ip6Address> testVec1(testArray1, testArray1 + sizeof(testArray1) / sizeof(otbr::Ip6Address));
400     netif.UpdateIp6MulticastAddresses(testVec1);
401     std::vector<std::string> wpanMulAddrs = GetAllIp6MulAddrs(wpan);
402     EXPECT_EQ(wpanMulAddrs.size(), 4);
403     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kMulAddr1Str));
404     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr1Str));
405     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr2Str));
406     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr3Str));
407 
408     otbr::Ip6Address              testArray2[] = {kMulAddr1, kMulAddr2};
409     std::vector<otbr::Ip6Address> testVec2(testArray2, testArray2 + sizeof(testArray2) / sizeof(otbr::Ip6Address));
410     netif.UpdateIp6MulticastAddresses(testVec2);
411     wpanMulAddrs = GetAllIp6MulAddrs(wpan);
412     EXPECT_EQ(wpanMulAddrs.size(), 5);
413     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kMulAddr1Str));
414     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kMulAddr2Str));
415     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr1Str));
416     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr2Str));
417     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr3Str));
418 
419     otbr::Ip6Address              testArray3[] = {kDefaultMulAddr1};
420     std::vector<otbr::Ip6Address> testVec3(testArray3, testArray3 + sizeof(testArray3) / sizeof(otbr::Ip6Address));
421     netif.UpdateIp6MulticastAddresses(testVec3);
422     wpanMulAddrs = GetAllIp6MulAddrs(wpan);
423     EXPECT_EQ(wpanMulAddrs.size(), 3);
424     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr1Str));
425     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr2Str));
426     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr3Str));
427 
428     std::vector<otbr::Ip6Address> empty;
429     netif.UpdateIp6MulticastAddresses(empty);
430     wpanMulAddrs = GetAllIp6MulAddrs(wpan);
431     EXPECT_EQ(wpanMulAddrs.size(), 3);
432     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr1Str));
433     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr2Str));
434     EXPECT_THAT(wpanMulAddrs, ::testing::Contains(kDefaultMulAddr3Str));
435 
436     netif.Deinit();
437 }
438 
TEST(Netif,WpanIfStateChangesCorrectly_AfterSettingNetifState)439 TEST(Netif, WpanIfStateChangesCorrectly_AfterSettingNetifState)
440 {
441     otbr::Netif netif;
442     const char *wpan = "wpan0";
443     EXPECT_EQ(netif.Init(wpan, Ip6SendEmptyImpl), 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;
470     EXPECT_EQ(netif.Init("wpan0", Ip6SendEmptyImpl), 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 
TEST(Netif,WpanIfSendIp6PacketCorrectly_AfterReceivingOnIf)525 TEST(Netif, WpanIfSendIp6PacketCorrectly_AfterReceivingOnIf)
526 {
527     bool        received = false;
528     std::string receivedPayload;
529     const char *hello = "Hello Otbr Netif!";
530 
531     auto Ip6SendTestImpl = [&received, &receivedPayload](const uint8_t *aData, uint16_t aLength) {
532         const ip6_hdr *ipv6_header = reinterpret_cast<const ip6_hdr *>(aData);
533         if (ipv6_header->ip6_nxt == IPPROTO_UDP)
534         {
535             const uint8_t *udpPayload    = aData + aLength - ntohs(ipv6_header->ip6_plen) + sizeof(udphdr);
536             uint16_t       udpPayloadLen = ntohs(ipv6_header->ip6_plen) - sizeof(udphdr);
537             receivedPayload              = std::string(reinterpret_cast<const char *>(udpPayload), udpPayloadLen);
538 
539             received = true;
540         }
541 
542         return OTBR_ERROR_NONE;
543     };
544 
545     otbr::Netif netif;
546     EXPECT_EQ(netif.Init("wpan0", Ip6SendTestImpl), OT_ERROR_NONE);
547 
548     // OMR Prefix: fd76:a5d1:fcb0:1707::/64
549     const otIp6Address kOmr = {
550         {0xfd, 0x76, 0xa5, 0xd1, 0xfc, 0xb0, 0x17, 0x07, 0xf3, 0xc7, 0xd8, 0x8c, 0xef, 0xd1, 0x24, 0xa9}};
551     std::vector<otbr::Ip6AddressInfo> addrs = {
552         {kOmr, 64, 0, 1, 0},
553     };
554     netif.UpdateIp6UnicastAddresses(addrs);
555     netif.SetNetifState(true);
556 
557     // Send a UDP packet destined to an address with OMR prefix.
558     {
559         int                 sockFd;
560         const uint16_t      destPort = 12345;
561         struct sockaddr_in6 destAddr;
562         const char         *destIp = "fd76:a5d1:fcb0:1707:3f1:47ce:85d3:77f";
563 
564         if ((sockFd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
565         {
566             perror("socket creation failed");
567             exit(EXIT_FAILURE);
568         }
569 
570         memset(&destAddr, 0, sizeof(destAddr));
571         destAddr.sin6_family = AF_INET6;
572         destAddr.sin6_port   = htons(destPort);
573         inet_pton(AF_INET6, destIp, &(destAddr.sin6_addr));
574 
575         if (sendto(sockFd, hello, strlen(hello), MSG_CONFIRM, (const struct sockaddr *)&destAddr, sizeof(destAddr)) < 0)
576         {
577             FAIL() << "Failed to send UDP packet through WPAN interface";
578         }
579         close(sockFd);
580     }
581 
582     otbr::MainloopContext context;
583     while (!received)
584     {
585         context.mMaxFd   = -1;
586         context.mTimeout = {100, 0};
587         FD_ZERO(&context.mReadFdSet);
588         FD_ZERO(&context.mWriteFdSet);
589         FD_ZERO(&context.mErrorFdSet);
590 
591         netif.UpdateFdSet(&context);
592         int rval = select(context.mMaxFd + 1, &context.mReadFdSet, &context.mWriteFdSet, &context.mErrorFdSet,
593                           &context.mTimeout);
594         if (rval < 0)
595         {
596             perror("select failed");
597             exit(EXIT_FAILURE);
598         }
599         netif.Process(&context);
600     }
601 
602     EXPECT_STREQ(receivedPayload.c_str(), hello);
603 
604     netif.Deinit();
605 }
606 #endif // __linux__
607