• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2022, 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 "net/nat64_translator.hpp"
30 
31 #include "test_platform.h"
32 #include "test_util.hpp"
33 
34 #include <inttypes.h>
35 #include <string.h>
36 
37 #include "common/code_utils.hpp"
38 #include "common/debug.hpp"
39 #include "common/message.hpp"
40 #include "instance/instance.hpp"
41 #include "net/ip6.hpp"
42 
43 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
44 
45 namespace ot {
46 namespace BorderRouter {
47 
48 static ot::Instance *sInstance;
49 
DumpMessageInHex(const char * prefix,const uint8_t * aBuf,size_t aBufLen)50 void DumpMessageInHex(const char *prefix, const uint8_t *aBuf, size_t aBufLen)
51 {
52     // This function dumps all packets the output of this function can be imported to packet analyser for debugging.
53     printf("%s", prefix);
54     for (size_t i = 0; i < aBufLen; i++)
55     {
56         printf("%02x", aBuf[i]);
57     }
58     printf("\n");
59 }
60 
CheckMessage(const Message & aMessage,const uint8_t * aExpectedMessage,size_t aExpectedMessageLen)61 bool CheckMessage(const Message &aMessage, const uint8_t *aExpectedMessage, size_t aExpectedMessageLen)
62 {
63     uint8_t  readMessage[OPENTHREAD_CONFIG_IP6_MAX_DATAGRAM_LENGTH];
64     uint16_t messageLength;
65     bool     success = true;
66 
67     success       = success && (aMessage.GetLength() == aExpectedMessageLen);
68     messageLength = aMessage.ReadBytes(0, readMessage, aMessage.GetLength());
69     success       = success && (aExpectedMessageLen == messageLength);
70     success       = success && (memcmp(readMessage, aExpectedMessage, aExpectedMessageLen) == 0);
71 
72     if (!success)
73     {
74         printf("Expected Message\n");
75         for (size_t i = 0; i < aExpectedMessageLen; i++)
76         {
77             printf("%02x%c", aExpectedMessage[i], " \n"[(i & 0xf) == 0xf]);
78         }
79         printf("\n");
80         printf("Actual Message\n");
81         for (uint16_t i = 0; i < messageLength; i++)
82         {
83             printf("%02x%c", readMessage[i], " \n"[(i & 0xf) == 0xf]);
84         }
85         printf("\n");
86     }
87 
88     return success;
89 }
90 
91 template <size_t N>
TestCase6To4(const char * aTestName,const uint8_t (& aIp6Message)[N],Nat64::Translator::Result aResult,const uint8_t * aOutMessage,size_t aOutMessageLen)92 void TestCase6To4(const char *aTestName,
93                   const uint8_t (&aIp6Message)[N],
94                   Nat64::Translator::Result aResult,
95                   const uint8_t            *aOutMessage,
96                   size_t                    aOutMessageLen)
97 {
98     Message *msg = sInstance->Get<Ip6::Ip6>().NewMessage(0);
99 
100     printf("Testing NAT64 6 to 4: %s\n", aTestName);
101 
102     VerifyOrQuit(msg != nullptr);
103     SuccessOrQuit(msg->AppendBytes(aIp6Message, N));
104 
105     DumpMessageInHex("I ", aIp6Message, N);
106 
107     VerifyOrQuit(sInstance->Get<Nat64::Translator>().TranslateFromIp6(*msg) == aResult);
108 
109     if (aOutMessage != nullptr)
110     {
111         DumpMessageInHex("O ", aOutMessage, aOutMessageLen);
112         VerifyOrQuit(CheckMessage(*msg, aOutMessage, aOutMessageLen));
113     }
114 
115     printf("  ... PASS\n");
116 }
117 
118 template <size_t N>
TestCase4To6(const char * aTestName,const uint8_t (& aIp4Message)[N],Nat64::Translator::Result aResult,const uint8_t * aOutMessage,size_t aOutMessageLen)119 void TestCase4To6(const char *aTestName,
120                   const uint8_t (&aIp4Message)[N],
121                   Nat64::Translator::Result aResult,
122                   const uint8_t            *aOutMessage,
123                   size_t                    aOutMessageLen)
124 {
125     Message *msg = sInstance->Get<Ip6::Ip6>().NewMessage(0);
126 
127     printf("Testing NAT64 4 to 6: %s\n", aTestName);
128 
129     VerifyOrQuit(msg != nullptr);
130     SuccessOrQuit(msg->AppendBytes(aIp4Message, N));
131 
132     DumpMessageInHex("I ", aIp4Message, N);
133 
134     VerifyOrQuit(sInstance->Get<Nat64::Translator>().TranslateToIp6(*msg) == aResult);
135 
136     if (aOutMessage != nullptr)
137     {
138         DumpMessageInHex("O ", aOutMessage, aOutMessageLen);
139         VerifyOrQuit(CheckMessage(*msg, aOutMessage, aOutMessageLen));
140     }
141 
142     printf("  ... PASS\n");
143 }
144 
PrintCounters(const otNat64Counters & aCounter)145 void PrintCounters(const otNat64Counters &aCounter)
146 {
147     printf(" ... 4To6Packets = %" PRIu64 "\n", aCounter.m4To6Packets);
148     printf(" ... 4To6Bytes   = %" PRIu64 "\n", aCounter.m4To6Bytes);
149     printf(" ... 6To4Packets = %" PRIu64 "\n", aCounter.m6To4Packets);
150     printf(" ... 6To4Bytes   = %" PRIu64 "\n", aCounter.m6To4Bytes);
151 }
152 
PrintProtocolCounters(const otNat64ProtocolCounters & aCounter)153 void PrintProtocolCounters(const otNat64ProtocolCounters &aCounter)
154 {
155     printf(" Total \n");
156     PrintCounters(aCounter.mTotal);
157     printf(" ICMP \n");
158     PrintCounters(aCounter.mIcmp);
159     printf(" UDP \n");
160     PrintCounters(aCounter.mUdp);
161     printf(" TCP \n");
162     PrintCounters(aCounter.mTcp);
163 }
164 
VerifyCounters(const otNat64ProtocolCounters & aExpected,const otNat64ProtocolCounters & aActual)165 void VerifyCounters(const otNat64ProtocolCounters &aExpected, const otNat64ProtocolCounters &aActual)
166 {
167     printf("Expected packet counters: \n");
168     PrintProtocolCounters(aExpected);
169     printf("Actual packet counters: \n");
170     PrintProtocolCounters(aActual);
171     VerifyOrQuit(memcmp(&aExpected, &aActual, sizeof(aActual)) == 0);
172     printf("  ... PASS\n");
173 }
174 
TestNat64(void)175 void TestNat64(void)
176 {
177     Ip6::Prefix  nat64prefix;
178     Ip4::Cidr    nat64cidr;
179     Ip6::Address ip6Source;
180     Ip6::Address ip6Dest;
181 
182     sInstance = testInitInstance();
183 
184     {
185         const uint8_t ip6Address[] = {0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
187         const uint8_t ip4Address[] = {192, 168, 123, 1};
188 
189         nat64cidr.Set(ip4Address, 32);
190         nat64prefix.Set(ip6Address, 96);
191         SuccessOrQuit(sInstance->Get<Nat64::Translator>().SetIp4Cidr(nat64cidr));
192         sInstance->Get<Nat64::Translator>().SetNat64Prefix(nat64prefix);
193     }
194 
195     {
196         // fd02::1               fd01::ac10:f3c5       UDP      52     43981 → 4660 Len=4
197         const uint8_t kIp6Packet[] = {
198             0x60, 0x08, 0x6e, 0x38, 0x00, 0x0c, 0x11, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199             0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200             172,  16,   243,  197,  0xab, 0xcd, 0x12, 0x34, 0x00, 0x0c, 0xe3, 0x31, 0x61, 0x62, 0x63, 0x64,
201         };
202         // 192.168.123.1         172.16.243.197        UDP      32     43981 → 4660 Len=4
203         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x9f,
204                                       0x4d, 192,  168,  123,  1,    172,  16,   243,  197,  0xab, 0xcd,
205                                       0x12, 0x34, 0x00, 0x0c, 0xa1, 0x8d, 0x61, 0x62, 0x63, 0x64};
206 
207         TestCase6To4("good v6 udp datagram", kIp6Packet, Nat64::Translator::kForward, kIp4Packet, sizeof(kIp4Packet));
208     }
209 
210     {
211         // 172.16.243.197        192.168.123.1         UDP      32     43981 → 4660 Len=4
212         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x11, 0xa0,
213                                       0x4d, 172,  16,   243,  197,  192,  168,  123,  1,    0xab, 0xcd,
214                                       0x12, 0x34, 0x00, 0x0c, 0xa1, 0x8d, 0x61, 0x62, 0x63, 0x64};
215         // fd01::ac10:f3c5       fd02::1               UDP      52     43981 → 4660 Len=4
216         const uint8_t kIp6Packet[] = {
217             0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x3f, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218             0x00, 0x00, 172,  16,   243,  197,  0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219             0x00, 0x00, 0x00, 0x01, 0xab, 0xcd, 0x12, 0x34, 0x00, 0x0c, 0xe3, 0x31, 0x61, 0x62, 0x63, 0x64,
220         };
221 
222         TestCase4To6("good v4 udp datagram", kIp4Packet, Nat64::Translator::kForward, kIp6Packet, sizeof(kIp6Packet));
223     }
224 
225     {
226         // fd02::1               fd01::ac10:f3c5       TCP      64     43981 → 4660 [ACK] Seq=1 Ack=1 Win=1 Len=4
227         const uint8_t kIp6Packet[] = {
228             0x60, 0x08, 0x6e, 0x38, 0x00, 0x18, 0x06, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230             0x00, 0x00, 0x00, 0x00, 172,  16,   243,  197,  0xab, 0xcd, 0x12, 0x34, 0x87, 0x65, 0x43, 0x21,
231             0x12, 0x34, 0x56, 0x78, 0x50, 0x10, 0x00, 0x01, 0x5f, 0xf8, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64,
232         };
233         // 192.168.123.1         172.16.243.197        TCP      44     43981 → 4660 [ACK] Seq=1 Ack=1 Win=1 Len=4
234         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x9f,
235                                       0x4c, 192,  168,  123,  1,    172,  16,   243,  197,  0xab, 0xcd,
236                                       0x12, 0x34, 0x87, 0x65, 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, 0x50,
237                                       0x10, 0x00, 0x01, 0x1e, 0x54, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64};
238 
239         TestCase6To4("good v6 tcp datagram", kIp6Packet, Nat64::Translator::kForward, kIp4Packet, sizeof(kIp4Packet));
240     }
241 
242     {
243         // 172.16.243.197        192.168.123.1         TCP      44     43981 → 4660 [ACK] Seq=1 Ack=1 Win=1 Len=4
244         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x9f,
245                                       0x4c, 172,  16,   243,  197,  192,  168,  123,  1,    0xab, 0xcd,
246                                       0x12, 0x34, 0x87, 0x65, 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, 0x50,
247                                       0x10, 0x00, 0x01, 0x1e, 0x54, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64};
248         // fd01::ac10:f3c5       fd02::1               TCP      64     43981 → 4660 [ACK] Seq=1 Ack=1 Win=1 Len=4
249         const uint8_t kIp6Packet[] = {
250             0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x40, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251             0x00, 0x00, 0x00, 0x00, 172,  16,   243,  197,  0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xab, 0xcd, 0x12, 0x34, 0x87, 0x65, 0x43, 0x21,
253             0x12, 0x34, 0x56, 0x78, 0x50, 0x10, 0x00, 0x01, 0x5f, 0xf8, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64,
254         };
255 
256         TestCase4To6("good v4 tcp datagram", kIp4Packet, Nat64::Translator::kForward, kIp6Packet, sizeof(kIp6Packet));
257     }
258 
259     {
260         // fd02::1         fd01::ac10:f3c5     ICMPv6   52     Echo (ping) request id=0xaabb, seq=1, hop limit=64
261         const uint8_t kIp6Packet[] = {
262             0x60, 0x08, 0x6e, 0x38, 0x00, 0x0c, 0x3a, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263             0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264             172,  16,   243,  197,  0x80, 0x00, 0x76, 0x59, 0xaa, 0xbb, 0x00, 0x01, 0x61, 0x62, 0x63, 0x64,
265         };
266         // 192.168.123.1   172.16.243.197      ICMP     32     Echo (ping) request  id=0xaabb, seq=1/256, ttl=63
267         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x9f,
268                                       0x5d, 192,  168,  123,  1,    172,  16,   243,  197,  0x08, 0x00,
269                                       0x88, 0x7c, 0xaa, 0xbb, 0x00, 0x01, 0x61, 0x62, 0x63, 0x64};
270 
271         TestCase6To4("good v6 icmp ping request datagram", kIp6Packet, Nat64::Translator::kForward, kIp4Packet,
272                      sizeof(kIp4Packet));
273     }
274 
275     {
276         // 172.16.243.197        192.168.123.1         ICMP     32     Echo (ping) reply    id=0xaabb, seq=1/256, ttl=63
277         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0xa0,
278                                       0x5d, 172,  16,   243,  197,  192,  168,  123,  1,    0x00, 0x00,
279                                       0x90, 0x7c, 0xaa, 0xbb, 0x00, 0x01, 0x61, 0x62, 0x63, 0x64};
280         // fd01::ac10:f3c5       fd02::1               ICMPv6   52     Echo (ping) reply id=0xaabb, seq=1, hop limit=62
281         const uint8_t kIp6Packet[] = {
282             0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x3a, 0x3f, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283             0x00, 0x00, 172,  16,   243,  197,  0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284             0x00, 0x00, 0x00, 0x01, 0x81, 0x00, 0x75, 0x59, 0xaa, 0xbb, 0x00, 0x01, 0x61, 0x62, 0x63, 0x64,
285         };
286 
287         TestCase4To6("good v4 icmp ping response datagram", kIp4Packet, Nat64::Translator::kForward, kIp6Packet,
288                      sizeof(kIp6Packet));
289     }
290 
291     {
292         // fd02::1               N/A                   IPv6     39     Invalid IPv6 header
293         const uint8_t kIp6Packet[] = {0x60, 0x08, 0x6e, 0x38, 0x00, 0x0c, 0x11, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00,
294                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x01,
295                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 172,  16,   243};
296 
297         TestCase6To4("bad v6 datagram", kIp6Packet, Nat64::Translator::kDrop, nullptr, 0);
298     }
299 
300     {
301         // 172.16.243.197        N/A                   IPv4     19     [Malformed Packet]
302         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x11,
303                                       0xa0, 0x4c, 172,  16,   243,  197,  192,  168,  123};
304 
305         TestCase4To6("bad v4 datagram", kIp4Packet, Nat64::Translator::kDrop, nullptr, 0);
306     }
307 
308     {
309         // 172.16.243.197        192.168.123.2         UDP      32     43981 → 4660 Len=4
310         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x11, 0xa0,
311                                       0x4c, 172,  16,   243,  197,  192,  168,  123,  2,    0xab, 0xcd,
312                                       0x12, 0x34, 0x00, 0x0c, 0xa1, 0x8c, 0x61, 0x62, 0x63, 0x64};
313 
314         TestCase4To6("no v4 mapping", kIp4Packet, Nat64::Translator::kDrop, nullptr, 0);
315     }
316 
317     {
318         // fd02::2               fd01::ac10:f3c5       UDP      52     43981 → 4660 Len=4
319         const uint8_t kIp6Packet[] = {
320             0x60, 0x08, 0x6e, 0x38, 0x00, 0x0c, 0x11, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321             0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322             172,  16,   243,  197,  0xab, 0xcd, 0x12, 0x34, 0x00, 0x0c, 0xe3, 0x30, 0x61, 0x62, 0x63, 0x64,
323         };
324 
325         TestCase6To4("mapping pool exhausted", kIp6Packet, Nat64::Translator::kDrop, nullptr, 0);
326     }
327 
328     testFreeInstance(sInstance);
329 }
330 
TestPacketCounter(void)331 void TestPacketCounter(void)
332 {
333     Ip6::Prefix  nat64prefix;
334     Ip4::Cidr    nat64cidr;
335     Ip6::Address ip6Source;
336     Ip6::Address ip6Dest;
337 
338     printf("Test: Packet counter is cleared for new mappings.\n");
339 
340     sInstance = testInitInstance();
341 
342     {
343         const uint8_t ip6Address[] = {0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
345         const uint8_t ip4Address[] = {192, 168, 123, 1};
346 
347         nat64cidr.Set(ip4Address, 32);
348         nat64prefix.Set(ip6Address, 96);
349         SuccessOrQuit(sInstance->Get<Nat64::Translator>().SetIp4Cidr(nat64cidr));
350         sInstance->Get<Nat64::Translator>().SetNat64Prefix(nat64prefix);
351     }
352 
353     // Step 1: Make the mapping table dirty.
354     {
355         // fd02::1               fd01::ac10:f3c5       UDP      52     43981 → 4660 Len=4
356         const uint8_t kIp6Packet[] = {
357             0x60, 0x08, 0x6e, 0x38, 0x00, 0x0c, 0x11, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358             0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359             172,  16,   243,  197,  0xab, 0xcd, 0x12, 0x34, 0x00, 0x0c, 0xe3, 0x31, 0x61, 0x62, 0x63, 0x64,
360         };
361         // 192.168.123.1         172.16.243.197        UDP      32     43981 → 4660 Len=4
362         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x9f,
363                                       0x4d, 192,  168,  123,  1,    172,  16,   243,  197,  0xab, 0xcd,
364                                       0x12, 0x34, 0x00, 0x0c, 0xa1, 0x8d, 0x61, 0x62, 0x63, 0x64};
365 
366         TestCase6To4("initial translation", kIp6Packet, Nat64::Translator::kForward, kIp4Packet, sizeof(kIp4Packet));
367     }
368 
369     {
370         Nat64::Translator::AddressMappingIterator iter;
371         otNat64AddressMapping                     mapping;
372         size_t                                    totalMappingCount = 0;
373 
374         sInstance->Get<Nat64::Translator>().InitAddressMappingIterator(iter);
375         while (sInstance->Get<Nat64::Translator>().GetNextAddressMapping(iter, mapping) == kErrorNone)
376         {
377             totalMappingCount++;
378             VerifyCounters(otNat64ProtocolCounters{.mTotal =
379                                                        {
380                                                            .m4To6Packets = 0,
381                                                            .m4To6Bytes   = 0,
382                                                            .m6To4Packets = 1,
383                                                            .m6To4Bytes   = 12,
384                                                        },
385                                                    .mIcmp =
386                                                        {
387                                                            .m4To6Packets = 0,
388                                                            .m4To6Bytes   = 0,
389                                                            .m6To4Packets = 0,
390                                                            .m6To4Bytes   = 0,
391                                                        },
392                                                    .mUdp =
393                                                        {
394                                                            .m4To6Packets = 0,
395                                                            .m4To6Bytes   = 0,
396                                                            .m6To4Packets = 1,
397                                                            .m6To4Bytes   = 12,
398                                                        },
399                                                    .mTcp =
400                                                        {
401                                                            .m4To6Packets = 0,
402                                                            .m4To6Bytes   = 0,
403                                                            .m6To4Packets = 0,
404                                                            .m6To4Bytes   = 0,
405                                                        }},
406                            mapping.mCounters);
407         }
408         VerifyOrQuit(totalMappingCount == 1);
409     }
410 
411     // Step 2: Release the mapping table item.
412     {
413         const uint8_t ip6Address[] = {0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
415         const uint8_t ip4Address[] = {192, 168, 124, 1};
416 
417         nat64cidr.Set(ip4Address, 32);
418         nat64prefix.Set(ip6Address, 96);
419         SuccessOrQuit(sInstance->Get<Nat64::Translator>().SetIp4Cidr(nat64cidr));
420         sInstance->Get<Nat64::Translator>().SetNat64Prefix(nat64prefix);
421     }
422 
423     // Step 3: Reuse the same object for new mapping table item.
424     // If the counters are not reset, the verification below will fail.
425     {
426         // fd02::1               fd01::ac10:f3c5       UDP      52     43981 → 4660 Len=4
427         const uint8_t kIp6Packet[] = {
428             0x60, 0x08, 0x6e, 0x38, 0x00, 0x0c, 0x11, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429             0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430             172,  16,   243,  197,  0xab, 0xcd, 0x12, 0x34, 0x00, 0x0c, 0xe3, 0x31, 0x61, 0x62, 0x63, 0x64,
431         };
432         // 192.168.124.1         172.16.243.197        UDP      32     43981 → 4660 Len=4
433         const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x9e,
434                                       0x4d, 192,  168,  124,  1,    172,  16,   243,  197,  0xab, 0xcd,
435                                       0x12, 0x34, 0x00, 0x0c, 0xa0, 0x8d, 0x61, 0x62, 0x63, 0x64};
436 
437         TestCase6To4("translation with new mapping", kIp6Packet, Nat64::Translator::kForward, kIp4Packet,
438                      sizeof(kIp4Packet));
439     }
440 
441     {
442         Nat64::Translator::AddressMappingIterator iter;
443         otNat64AddressMapping                     mapping;
444         size_t                                    totalMappingCount = 0;
445 
446         sInstance->Get<Nat64::Translator>().InitAddressMappingIterator(iter);
447         while (sInstance->Get<Nat64::Translator>().GetNextAddressMapping(iter, mapping) == kErrorNone)
448         {
449             totalMappingCount++;
450             VerifyCounters(otNat64ProtocolCounters{.mTotal =
451                                                        {
452                                                            .m4To6Packets = 0,
453                                                            .m4To6Bytes   = 0,
454                                                            .m6To4Packets = 1,
455                                                            .m6To4Bytes   = 12,
456                                                        },
457                                                    .mIcmp =
458                                                        {
459                                                            .m4To6Packets = 0,
460                                                            .m4To6Bytes   = 0,
461                                                            .m6To4Packets = 0,
462                                                            .m6To4Bytes   = 0,
463                                                        },
464                                                    .mUdp =
465                                                        {
466                                                            .m4To6Packets = 0,
467                                                            .m4To6Bytes   = 0,
468                                                            .m6To4Packets = 1,
469                                                            .m6To4Bytes   = 12,
470                                                        },
471                                                    .mTcp =
472                                                        {
473                                                            .m4To6Packets = 0,
474                                                            .m4To6Bytes   = 0,
475                                                            .m6To4Packets = 0,
476                                                            .m6To4Bytes   = 0,
477                                                        }},
478                            mapping.mCounters);
479         }
480         VerifyOrQuit(totalMappingCount == 1);
481     }
482 }
483 
484 } // namespace BorderRouter
485 } // namespace ot
486 
487 #endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
488 
main(void)489 int main(void)
490 {
491 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
492     ot::BorderRouter::TestNat64();
493     ot::BorderRouter::TestPacketCounter();
494     printf("All tests passed\n");
495 #else  // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
496     printf("NAT64 is not enabled\n");
497 #endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
498     return 0;
499 }
500