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