1 /*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * clatd_test.cpp - unit tests for clatd
17 */
18
19 #include <iostream>
20
21 #include <arpa/inet.h>
22 #include <netinet/in6.h>
23 #include <stdio.h>
24 #include <sys/uio.h>
25
26 #include <gtest/gtest.h>
27
28 #include "netutils/ifc.h"
29 #include "tun_interface.h"
30
31 extern "C" {
32 #include "clatd.h"
33 #include "config.h"
34 #include "getaddr.h"
35 #include "netutils/checksum.h"
36 #include "translate.h"
37 }
38
39 // For convenience.
40 #define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0])
41
42 using android::net::TunInterface;
43
44 // Default translation parameters.
45 static const char kIPv4LocalAddr[] = "192.0.0.4";
46 static const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
47 static const char kIPv6PlatSubnet[] = "64:ff9b::";
48
49 // clang-format off
50 // Test packet portions. Defined as macros because it's easy to concatenate them to make packets.
51 #define IPV4_HEADER(p, c1, c2) \
52 0x45, 0x00, 0, 41, /* Version=4, IHL=5, ToS=0x80, len=41 */ \
53 0x00, 0x00, 0x40, 0x00, /* ID=0x0000, flags=IP_DF, offset=0 */ \
54 55, (p), (c1), (c2), /* TTL=55, protocol=p, checksum=c1,c2 */ \
55 192, 0, 0, 4, /* Src=192.0.0.4 */ \
56 8, 8, 8, 8, /* Dst=8.8.8.8 */
57 #define IPV4_UDP_HEADER IPV4_HEADER(IPPROTO_UDP, 0x73, 0xb0)
58 #define IPV4_ICMP_HEADER IPV4_HEADER(IPPROTO_ICMP, 0x73, 0xc0)
59
60 #define IPV6_HEADER(p) \
61 0x60, 0x00, 0, 0, /* Version=6, tclass=0x00, flowlabel=0 */ \
62 0, 21, (p), 55, /* plen=11, nxthdr=p, hlim=55 */ \
63 0x20, 0x01, 0x0d, 0xb8, /* Src=2001:db8:0:b11::464 */ \
64 0x00, 0x00, 0x0b, 0x11, \
65 0x00, 0x00, 0x00, 0x00, \
66 0x00, 0x00, 0x04, 0x64, \
67 0x00, 0x64, 0xff, 0x9b, /* Dst=64:ff9b::8.8.8.8 */ \
68 0x00, 0x00, 0x00, 0x00, \
69 0x00, 0x00, 0x00, 0x00, \
70 0x08, 0x08, 0x08, 0x08,
71 #define IPV6_UDP_HEADER IPV6_HEADER(IPPROTO_UDP)
72 #define IPV6_ICMPV6_HEADER IPV6_HEADER(IPPROTO_ICMPV6)
73
74 #define UDP_LEN 21
75 #define UDP_HEADER \
76 0xc8, 0x8b, 0, 53, /* Port 51339->53 */ \
77 0x00, UDP_LEN, 0, 0, /* Length 21, checksum empty for now */
78
79 #define PAYLOAD 'H', 'e', 'l', 'l', 'o', ' ', 0x4e, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0x00
80
81 #define IPV4_PING \
82 0x08, 0x00, 0x88, 0xd0, /* Type 8, code 0, checksum 0x88d0 */ \
83 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
84
85 #define IPV6_PING \
86 0x80, 0x00, 0xc3, 0x42, /* Type 128, code 0, checksum 0xc342 */ \
87 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
88
89 // Macros to return pseudo-headers from packets.
90 #define IPV4_PSEUDOHEADER(ip, tlen) \
91 ip[12], ip[13], ip[14], ip[15], /* Source address */ \
92 ip[16], ip[17], ip[18], ip[19], /* Destination address */ \
93 0, ip[9], /* 0, protocol */ \
94 ((tlen) >> 16) & 0xff, (tlen) & 0xff, /* Transport length */
95
96 #define IPV6_PSEUDOHEADER(ip6, protocol, tlen) \
97 ip6[8], ip6[9], ip6[10], ip6[11], /* Source address */ \
98 ip6[12], ip6[13], ip6[14], ip6[15], \
99 ip6[16], ip6[17], ip6[18], ip6[19], \
100 ip6[20], ip6[21], ip6[22], ip6[23], \
101 ip6[24], ip6[25], ip6[26], ip6[27], /* Destination address */ \
102 ip6[28], ip6[29], ip6[30], ip6[31], \
103 ip6[32], ip6[33], ip6[34], ip6[35], \
104 ip6[36], ip6[37], ip6[38], ip6[39], \
105 ((tlen) >> 24) & 0xff, /* Transport length */ \
106 ((tlen) >> 16) & 0xff, \
107 ((tlen) >> 8) & 0xff, \
108 (tlen) & 0xff, \
109 0, 0, 0, (protocol),
110
111 // A fragmented DNS request.
112 static const uint8_t kIPv4Frag1[] = {
113 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x00, 0x40, 0x11,
114 0x8c, 0x6d, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
115 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
116 0x01, 0x00, 0x00, 0x01, 0x00, 0x00
117 };
118 static const uint8_t kIPv4Frag2[] = {
119 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x02, 0x40, 0x11,
120 0x8c, 0x6b, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
121 0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06,
122 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65
123 };
124 static const uint8_t kIPv4Frag3[] = {
125 0x45, 0x00, 0x00, 0x1d, 0xfe, 0x47, 0x00, 0x04, 0x40, 0x11,
126 0xac, 0x70, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
127 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
128 };
129 static const uint8_t *kIPv4Fragments[] = { kIPv4Frag1, kIPv4Frag2, kIPv4Frag3 };
130 static const size_t kIPv4FragLengths[] = { sizeof(kIPv4Frag1), sizeof(kIPv4Frag2),
131 sizeof(kIPv4Frag3) };
132
133 static const uint8_t kIPv6Frag1[] = {
134 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
135 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
138 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x47, 0x14, 0x5d,
139 0x00, 0x35, 0x00, 0x29, 0xeb, 0x91, 0x50, 0x47, 0x01, 0x00,
140 0x00, 0x01, 0x00, 0x00
141 };
142
143 static const uint8_t kIPv6Frag2[] = {
144 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
145 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
148 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0xfe, 0x47, 0x00, 0x00,
149 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f,
150 0x6f, 0x67, 0x6c, 0x65
151 };
152
153 static const uint8_t kIPv6Frag3[] = {
154 0x60, 0x00, 0x00, 0x00, 0x00, 0x11, 0x2c, 0x40, 0x20, 0x01,
155 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
158 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0xfe, 0x47, 0x03, 0x63,
159 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
160 };
161 static const uint8_t *kIPv6Fragments[] = { kIPv6Frag1, kIPv6Frag2, kIPv6Frag3 };
162 static const size_t kIPv6FragLengths[] = { sizeof(kIPv6Frag1), sizeof(kIPv6Frag2),
163 sizeof(kIPv6Frag3) };
164
165 static const uint8_t kReassembledIPv4[] = {
166 0x45, 0x00, 0x00, 0x3d, 0xfe, 0x47, 0x00, 0x00, 0x40, 0x11,
167 0xac, 0x54, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
168 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
169 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67,
171 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
172 0x01
173 };
174 // clang-format on
175
176 // Expected checksums.
177 static const uint32_t kUdpPartialChecksum = 0xd5c8;
178 static const uint32_t kPayloadPartialChecksum = 0x31e9c;
179 static const uint16_t kUdpV4Checksum = 0xd0c7;
180 static const uint16_t kUdpV6Checksum = 0xa74a;
181
ip_version(const uint8_t * packet)182 uint8_t ip_version(const uint8_t *packet) {
183 uint8_t version = packet[0] >> 4;
184 return version;
185 }
186
is_ipv4_fragment(struct iphdr * ip)187 int is_ipv4_fragment(struct iphdr *ip) {
188 // A packet is a fragment if its fragment offset is nonzero or if the MF flag is set.
189 return ntohs(ip->frag_off) & (IP_OFFMASK | IP_MF);
190 }
191
is_ipv6_fragment(struct ip6_hdr * ip6,size_t len)192 int is_ipv6_fragment(struct ip6_hdr *ip6, size_t len) {
193 if (ip6->ip6_nxt != IPPROTO_FRAGMENT) {
194 return 0;
195 }
196 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
197 return len >= sizeof(*ip6) + sizeof(*frag) &&
198 (frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG));
199 }
200
ipv4_fragment_offset(struct iphdr * ip)201 int ipv4_fragment_offset(struct iphdr *ip) {
202 return ntohs(ip->frag_off) & IP_OFFMASK;
203 }
204
ipv6_fragment_offset(struct ip6_frag * frag)205 int ipv6_fragment_offset(struct ip6_frag *frag) {
206 return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3);
207 }
208
check_packet(const uint8_t * packet,size_t len,const char * msg)209 void check_packet(const uint8_t *packet, size_t len, const char *msg) {
210 void *payload;
211 size_t payload_length = 0;
212 uint32_t pseudo_checksum = 0;
213 uint8_t protocol = 0;
214 int version = ip_version(packet);
215 switch (version) {
216 case 4: {
217 struct iphdr *ip = (struct iphdr *)packet;
218 ASSERT_GE(len, sizeof(*ip)) << msg << ": IPv4 packet shorter than IPv4 header\n";
219 EXPECT_EQ(5, ip->ihl) << msg << ": Unsupported IP header length\n";
220 EXPECT_EQ(len, ntohs(ip->tot_len)) << msg << ": Incorrect IPv4 length\n";
221 EXPECT_EQ(0, ip_checksum(ip, sizeof(*ip))) << msg << ": Incorrect IP checksum\n";
222 protocol = ip->protocol;
223 payload = ip + 1;
224 if (!is_ipv4_fragment(ip)) {
225 payload_length = len - sizeof(*ip);
226 pseudo_checksum = ipv4_pseudo_header_checksum(ip, payload_length);
227 }
228 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP)
229 << msg << ": Unsupported IPv4 protocol " << protocol << "\n";
230 break;
231 }
232 case 6: {
233 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
234 ASSERT_GE(len, sizeof(*ip6)) << msg << ": IPv6 packet shorter than IPv6 header\n";
235 EXPECT_EQ(len - sizeof(*ip6), htons(ip6->ip6_plen)) << msg << ": Incorrect IPv6 length\n";
236
237 if (ip6->ip6_nxt == IPPROTO_FRAGMENT) {
238 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
239 ASSERT_GE(len, sizeof(*ip6) + sizeof(*frag))
240 << msg << ": IPv6 fragment: short fragment header\n";
241 protocol = frag->ip6f_nxt;
242 payload = frag + 1;
243 // Even though the packet has a Fragment header, it might not be a fragment.
244 if (!is_ipv6_fragment(ip6, len)) {
245 payload_length = len - sizeof(*ip6) - sizeof(*frag);
246 }
247 } else {
248 // Since there are no extension headers except Fragment, this must be the payload.
249 protocol = ip6->ip6_nxt;
250 payload = ip6 + 1;
251 payload_length = len - sizeof(*ip6);
252 }
253 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMPV6)
254 << msg << ": Unsupported IPv6 next header " << protocol;
255 if (payload_length) {
256 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, payload_length, protocol);
257 }
258 break;
259 }
260 default:
261 FAIL() << msg << ": Unsupported IP version " << version << "\n";
262 return;
263 }
264
265 // If we understand the payload, verify the checksum.
266 if (payload_length) {
267 uint16_t checksum;
268 switch (protocol) {
269 case IPPROTO_UDP:
270 case IPPROTO_TCP:
271 case IPPROTO_ICMPV6:
272 checksum = ip_checksum_finish(ip_checksum_add(pseudo_checksum, payload, payload_length));
273 break;
274 case IPPROTO_ICMP:
275 checksum = ip_checksum(payload, payload_length);
276 break;
277 default:
278 checksum = 0; // Don't check.
279 break;
280 }
281 EXPECT_EQ(0, checksum) << msg << ": Incorrect transport checksum\n";
282 }
283
284 if (protocol == IPPROTO_UDP) {
285 struct udphdr *udp = (struct udphdr *)payload;
286 EXPECT_NE(0, udp->check) << msg << ": UDP checksum 0 should be 0xffff";
287 // If this is not a fragment, check the UDP length field.
288 if (payload_length) {
289 EXPECT_EQ(payload_length, ntohs(udp->len)) << msg << ": Incorrect UDP length\n";
290 }
291 }
292 }
293
reassemble_packet(const uint8_t ** fragments,const size_t lengths[],int numpackets,uint8_t * reassembled,size_t * reassembled_len,const char * msg)294 void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int numpackets,
295 uint8_t *reassembled, size_t *reassembled_len, const char *msg) {
296 struct iphdr *ip = nullptr;
297 struct ip6_hdr *ip6 = nullptr;
298 size_t total_length, pos = 0;
299 uint8_t protocol = 0;
300 uint8_t version = ip_version(fragments[0]);
301
302 for (int i = 0; i < numpackets; i++) {
303 const uint8_t *packet = fragments[i];
304 int len = lengths[i];
305 int headersize, payload_offset;
306
307 ASSERT_EQ(ip_version(packet), version) << msg << ": Inconsistent fragment versions\n";
308 check_packet(packet, len, "Fragment sanity check");
309
310 switch (version) {
311 case 4: {
312 struct iphdr *ip_orig = (struct iphdr *)packet;
313 headersize = sizeof(*ip_orig);
314 ASSERT_TRUE(is_ipv4_fragment(ip_orig))
315 << msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n";
316 ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip) : 0))
317 << msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n";
318
319 headersize = sizeof(*ip_orig);
320 payload_offset = headersize;
321 if (pos == 0) {
322 ip = (struct iphdr *)reassembled;
323 }
324 break;
325 }
326 case 6: {
327 struct ip6_hdr *ip6_orig = (struct ip6_hdr *)packet;
328 struct ip6_frag *frag = (struct ip6_frag *)(ip6_orig + 1);
329 ASSERT_TRUE(is_ipv6_fragment(ip6_orig, len))
330 << msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n";
331 ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6) : 0))
332 << msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n";
333
334 headersize = sizeof(*ip6_orig);
335 payload_offset = sizeof(*ip6_orig) + sizeof(*frag);
336 if (pos == 0) {
337 ip6 = (struct ip6_hdr *)reassembled;
338 protocol = frag->ip6f_nxt;
339 }
340 break;
341 }
342 default:
343 FAIL() << msg << ": Invalid IP version << " << version;
344 }
345
346 // If this is the first fragment, copy the header.
347 if (pos == 0) {
348 ASSERT_LT(headersize, (int)*reassembled_len) << msg << ": Reassembly buffer too small\n";
349 memcpy(reassembled, packet, headersize);
350 total_length = headersize;
351 pos += headersize;
352 }
353
354 // Copy the payload.
355 int payload_length = len - payload_offset;
356 total_length += payload_length;
357 ASSERT_LT(total_length, *reassembled_len) << msg << ": Reassembly buffer too small\n";
358 memcpy(reassembled + pos, packet + payload_offset, payload_length);
359 pos += payload_length;
360 }
361
362 // Fix up the reassembled headers to reflect fragmentation and length (and IPv4 checksum).
363 ASSERT_EQ(total_length, pos) << msg << ": Reassembled packet length incorrect\n";
364 if (ip) {
365 ip->frag_off &= ~htons(IP_MF);
366 ip->tot_len = htons(total_length);
367 ip->check = 0;
368 ip->check = ip_checksum(ip, sizeof(*ip));
369 ASSERT_FALSE(is_ipv4_fragment(ip)) << msg << ": reassembled IPv4 packet is a fragment!\n";
370 }
371 if (ip6) {
372 ip6->ip6_nxt = protocol;
373 ip6->ip6_plen = htons(total_length - sizeof(*ip6));
374 ASSERT_FALSE(is_ipv6_fragment(ip6, ip6->ip6_plen))
375 << msg << ": reassembled IPv6 packet is a fragment!\n";
376 }
377
378 *reassembled_len = total_length;
379 }
380
check_data_matches(const void * expected,const void * actual,size_t len,const char * msg)381 void check_data_matches(const void *expected, const void *actual, size_t len, const char *msg) {
382 if (memcmp(expected, actual, len)) {
383 // Hex dump, 20 bytes per line, one space between bytes (1 byte = 3 chars), indented by 4.
384 int hexdump_len = len * 3 + (len / 20 + 1) * 5;
385 char expected_hexdump[hexdump_len], actual_hexdump[hexdump_len];
386 unsigned pos = 0;
387 for (unsigned i = 0; i < len; i++) {
388 if (i % 20 == 0) {
389 snprintf(expected_hexdump + pos, hexdump_len - pos, "\n ");
390 snprintf(actual_hexdump + pos, hexdump_len - pos, "\n ");
391 pos += 4;
392 }
393 snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)expected)[i]);
394 snprintf(actual_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)actual)[i]);
395 pos += 3;
396 }
397 FAIL() << msg << ": Data doesn't match"
398 << "\n Expected:" << (char *) expected_hexdump
399 << "\n Actual:" << (char *) actual_hexdump << "\n";
400 }
401 }
402
fix_udp_checksum(uint8_t * packet)403 void fix_udp_checksum(uint8_t *packet) {
404 uint32_t pseudo_checksum;
405 uint8_t version = ip_version(packet);
406 struct udphdr *udp;
407 switch (version) {
408 case 4: {
409 struct iphdr *ip = (struct iphdr *)packet;
410 udp = (struct udphdr *)(ip + 1);
411 pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len));
412 break;
413 }
414 case 6: {
415 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
416 udp = (struct udphdr *)(ip6 + 1);
417 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP);
418 break;
419 }
420 default:
421 FAIL() << "unsupported IP version" << version << "\n";
422 return;
423 }
424
425 udp->check = 0;
426 udp->check = ip_checksum_finish(ip_checksum_add(pseudo_checksum, udp, ntohs(udp->len)));
427 }
428
429 // Testing stub for send_rawv6. The real version uses sendmsg() with a
430 // destination IPv6 address, and attempting to call that on our test socketpair
431 // fd results in EINVAL.
send_rawv6(int fd,clat_packet out,int iov_len)432 extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) { writev(fd, out, iov_len); }
433
do_translate_packet(const uint8_t * original,size_t original_len,uint8_t * out,size_t * outlen,const char * msg)434 void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *out, size_t *outlen,
435 const char *msg) {
436 int fds[2];
437 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, fds)) {
438 abort();
439 }
440
441 char foo[512];
442 snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg);
443 check_packet(original, original_len, foo);
444
445 int read_fd, write_fd;
446 uint16_t expected_proto;
447 int version = ip_version(original);
448 switch (version) {
449 case 4:
450 expected_proto = htons(ETH_P_IPV6);
451 read_fd = fds[1];
452 write_fd = fds[0];
453 break;
454 case 6:
455 expected_proto = htons(ETH_P_IP);
456 read_fd = fds[0];
457 write_fd = fds[1];
458 break;
459 default:
460 FAIL() << msg << ": Unsupported IP version " << version << "\n";
461 break;
462 }
463
464 translate_packet(write_fd, (version == 4), original, original_len);
465
466 snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
467 if (version == 6) {
468 // Translating to IPv4. Expect a tun header.
469 struct tun_pi new_tun_header;
470 struct iovec iov[] = {
471 { &new_tun_header, sizeof(new_tun_header) },
472 { out, *outlen },
473 };
474
475 int len = readv(read_fd, iov, 2);
476 if (len > (int)sizeof(new_tun_header)) {
477 ASSERT_LT((size_t)len, *outlen) << msg << ": Translated packet buffer too small\n";
478 EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
479 *outlen = len - sizeof(new_tun_header);
480 check_packet(out, *outlen, msg);
481 } else {
482 FAIL() << msg << ": Packet was not translated: len=" << len;
483 *outlen = 0;
484 }
485 } else {
486 // Translating to IPv6. Expect raw packet.
487 *outlen = read(read_fd, out, *outlen);
488 check_packet(out, *outlen, msg);
489 }
490 }
491
check_translated_packet(const uint8_t * original,size_t original_len,const uint8_t * expected,size_t expected_len,const char * msg)492 void check_translated_packet(const uint8_t *original, size_t original_len, const uint8_t *expected,
493 size_t expected_len, const char *msg) {
494 uint8_t translated[MAXMTU];
495 size_t translated_len = sizeof(translated);
496 do_translate_packet(original, original_len, translated, &translated_len, msg);
497 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
498 check_data_matches(expected, translated, translated_len, msg);
499 }
500
check_fragment_translation(const uint8_t * original[],const size_t original_lengths[],const uint8_t * expected[],const size_t expected_lengths[],int numfragments,const char * msg)501 void check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
502 const uint8_t *expected[], const size_t expected_lengths[],
503 int numfragments, const char *msg) {
504 for (int i = 0; i < numfragments; i++) {
505 // Check that each of the fragments translates as expected.
506 char frag_msg[512];
507 snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
508 check_translated_packet(original[i], original_lengths[i], expected[i], expected_lengths[i],
509 frag_msg);
510 }
511
512 // Sanity check that reassembling the original and translated fragments produces valid packets.
513 uint8_t reassembled[MAXMTU];
514 size_t reassembled_len = sizeof(reassembled);
515 reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
516 check_packet(reassembled, reassembled_len, msg);
517
518 uint8_t translated[MAXMTU];
519 size_t translated_len = sizeof(translated);
520 do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
521 check_packet(translated, translated_len, msg);
522 }
523
get_transport_checksum(const uint8_t * packet)524 int get_transport_checksum(const uint8_t *packet) {
525 struct iphdr *ip;
526 struct ip6_hdr *ip6;
527 uint8_t protocol;
528 const void *payload;
529
530 int version = ip_version(packet);
531 switch (version) {
532 case 4:
533 ip = (struct iphdr *)packet;
534 if (is_ipv4_fragment(ip)) {
535 return -1;
536 }
537 protocol = ip->protocol;
538 payload = ip + 1;
539 break;
540 case 6:
541 ip6 = (struct ip6_hdr *)packet;
542 protocol = ip6->ip6_nxt;
543 payload = ip6 + 1;
544 break;
545 default:
546 return -1;
547 }
548
549 switch (protocol) {
550 case IPPROTO_UDP:
551 return ((struct udphdr *)payload)->check;
552
553 case IPPROTO_TCP:
554 return ((struct tcphdr *)payload)->check;
555
556 case IPPROTO_FRAGMENT:
557 default:
558 return -1;
559 }
560 }
561
makeTunData()562 static tun_data makeTunData() {
563 // Create some fake but realistic-looking sockets so update_clat_ipv6_address doesn't balk.
564 return {
565 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
566 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
567 .fd4 = socket(AF_UNIX, SOCK_DGRAM, 0),
568 };
569 }
570
freeTunData(tun_data * tunnel)571 void freeTunData(tun_data *tunnel) {
572 close(tunnel->write_fd6);
573 close(tunnel->read_fd6);
574 close(tunnel->fd4);
575 }
576
577 struct clat_config Global_Clatd_Config;
578
579 class ClatdTest : public ::testing::Test {
580 protected:
581 static TunInterface sTun;
582
SetUp()583 virtual void SetUp() {
584 inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
585 inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
586 memset(&Global_Clatd_Config.ipv6_local_subnet, 0, sizeof(in6_addr));
587 Global_Clatd_Config.native_ipv6_interface = const_cast<char *>(sTun.name().c_str());
588 }
589
590 // Static because setting up the tun interface takes about 40ms.
SetUpTestCase()591 static void SetUpTestCase() { ASSERT_EQ(0, sTun.init()); }
592
593 // Closing the socket removes the interface and IP addresses.
TearDownTestCase()594 static void TearDownTestCase() { sTun.destroy(); }
595 };
596
597 TunInterface ClatdTest::sTun;
598
expect_ipv6_addr_equal(struct in6_addr * expected,struct in6_addr * actual)599 void expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
600 if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
601 char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
602 inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
603 inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
604 FAIL()
605 << "Unexpected IPv6 address:: "
606 << "\n Expected: " << expected_str
607 << "\n Actual: " << actual_str
608 << "\n";
609 }
610 }
611
TEST_F(ClatdTest,TestIPv6PrefixEqual)612 TEST_F(ClatdTest, TestIPv6PrefixEqual) {
613 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
614 &Global_Clatd_Config.plat_subnet));
615 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
616 &Global_Clatd_Config.ipv6_local_subnet));
617
618 struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
619 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
620 EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
621
622 subnet2.s6_addr[6] = 0xff;
623 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
624 EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
625 }
626
TEST_F(ClatdTest,DetectMtu)627 TEST_F(ClatdTest, DetectMtu) {
628 // ::1 with bottom 32 bits set to 1 is still ::1 which routes via lo with mtu of 64KiB
629 ASSERT_EQ(detect_mtu(&in6addr_loopback, htonl(1), 0 /*MARK_UNSET*/), 65536);
630 }
631
TEST_F(ClatdTest,ConfigureTunIpManual)632 TEST_F(ClatdTest, ConfigureTunIpManual) {
633 // Create an interface for configure_tun_ip to configure and bring up.
634 TunInterface v4Iface;
635 ASSERT_EQ(0, v4Iface.init());
636 struct tun_data tunnel = makeTunData();
637 strlcpy(tunnel.device4, v4Iface.name().c_str(), sizeof(tunnel.device4));
638
639 configure_tun_ip(&tunnel, "192.0.2.1" /* v4_addr */, 1472);
640 EXPECT_EQ(inet_addr("192.0.2.1"), Global_Clatd_Config.ipv4_local_subnet.s_addr);
641
642 union anyip *ip = getinterface_ip(v4Iface.name().c_str(), AF_INET);
643 ASSERT_NE(nullptr, ip);
644 EXPECT_EQ(inet_addr("192.0.2.1"), ip->ip4.s_addr);
645 free(ip);
646
647 v4Iface.destroy();
648 }
649
TEST_F(ClatdTest,DataSanitycheck)650 TEST_F(ClatdTest, DataSanitycheck) {
651 // Sanity checks the data.
652 uint8_t v4_header[] = { IPV4_UDP_HEADER };
653 ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
654
655 uint8_t v6_header[] = { IPV6_UDP_HEADER };
656 ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
657
658 uint8_t udp_header[] = { UDP_HEADER };
659 ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
660
661 // Sanity checks check_packet.
662 struct udphdr *udp;
663 uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
664 udp = (struct udphdr *)(v4_udp_packet + sizeof(struct iphdr));
665 fix_udp_checksum(v4_udp_packet);
666 ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
667 check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
668
669 uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
670 udp = (struct udphdr *)(v6_udp_packet + sizeof(struct ip6_hdr));
671 fix_udp_checksum(v6_udp_packet);
672 ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
673 check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
674
675 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
676 check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
677
678 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
679 check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
680
681 // Sanity checks reassemble_packet.
682 uint8_t reassembled[MAXMTU];
683 size_t total_length = sizeof(reassembled);
684 reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), reassembled,
685 &total_length, "Reassembly sanity check");
686 check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
687 ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
688 ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *)reassembled))
689 << "Sanity check: reassembled packet is a fragment!\n";
690 check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
691
692 total_length = sizeof(reassembled);
693 reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments), reassembled,
694 &total_length, "IPv6 reassembly sanity check");
695 ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *)reassembled, total_length))
696 << "Sanity check: reassembled packet is a fragment!\n";
697 check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
698 }
699
TEST_F(ClatdTest,PseudoChecksum)700 TEST_F(ClatdTest, PseudoChecksum) {
701 uint32_t pseudo_checksum;
702
703 uint8_t v4_header[] = { IPV4_UDP_HEADER };
704 uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
705 pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *)v4_header, UDP_LEN);
706 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
707 ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
708 << "ipv4_pseudo_header_checksum incorrect\n";
709
710 uint8_t v6_header[] = { IPV6_UDP_HEADER };
711 uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
712 pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *)v6_header, UDP_LEN, IPPROTO_UDP);
713 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
714 ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
715 << "ipv6_pseudo_header_checksum incorrect\n";
716 }
717
TEST_F(ClatdTest,TransportChecksum)718 TEST_F(ClatdTest, TransportChecksum) {
719 uint8_t udphdr[] = { UDP_HEADER };
720 uint8_t payload[] = { PAYLOAD };
721 EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
722 << "UDP partial checksum\n";
723 EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
724 << "Payload partial checksum\n";
725
726 uint8_t ip[] = { IPV4_UDP_HEADER };
727 uint8_t ip6[] = { IPV6_UDP_HEADER };
728 uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *)ip, UDP_LEN);
729 uint32_t ipv6_pseudo_sum =
730 ipv6_pseudo_header_checksum((struct ip6_hdr *)ip6, UDP_LEN, IPPROTO_UDP);
731
732 EXPECT_NE(0, ipv4_pseudo_sum);
733 EXPECT_NE(0, ipv6_pseudo_sum);
734 EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum % 0xFFFF) << "IPv4 pseudo-checksum sanity check\n";
735 EXPECT_EQ(0x644dU, ipv6_pseudo_sum % 0xFFFF) << "IPv6 pseudo-checksum sanity check\n";
736 EXPECT_EQ(
737 kUdpV4Checksum,
738 ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
739 << "Unexpected UDP/IPv4 checksum\n";
740 EXPECT_EQ(
741 kUdpV6Checksum,
742 ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
743 << "Unexpected UDP/IPv6 checksum\n";
744
745 EXPECT_EQ(kUdpV6Checksum,
746 ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
747 << "Adjust IPv4/UDP checksum to IPv6\n";
748 EXPECT_EQ(kUdpV4Checksum,
749 ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
750 << "Adjust IPv6/UDP checksum to IPv4\n";
751 }
752
TEST_F(ClatdTest,AdjustChecksum)753 TEST_F(ClatdTest, AdjustChecksum) {
754 struct checksum_data {
755 uint16_t checksum;
756 uint32_t old_hdr_sum;
757 uint32_t new_hdr_sum;
758 uint16_t result;
759 } DATA[] = {
760 { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
761 { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
762 { 0xdd2f, 0x5555, 0x3285, 0x0000 },
763 { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
764 { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
765 };
766 unsigned i = 0;
767
768 for (i = 0; i < ARRAYSIZE(DATA); i++) {
769 struct checksum_data *data = DATA + i;
770 uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
771 EXPECT_EQ(result, data->result)
772 << "Incorrect checksum" << std::showbase << std::hex
773 << "\n Expected: " << data->result
774 << "\n Actual: " << result
775 << "\n checksum=" << data->checksum
776 << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
777 }
778 }
779
TEST_F(ClatdTest,Translate)780 TEST_F(ClatdTest, Translate) {
781 // This test uses hardcoded packets so the clatd address must be fixed.
782 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
783
784 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
785 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
786 fix_udp_checksum(udp_ipv4);
787 fix_udp_checksum(udp_ipv6);
788 check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
789 "UDP/IPv4 -> UDP/IPv6 translation");
790 check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
791 "UDP/IPv6 -> UDP/IPv4 translation");
792
793 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
794 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
795 check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
796 "ICMP->ICMPv6 translation");
797 check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
798 "ICMPv6->ICMP translation");
799 }
800
TEST_F(ClatdTest,Fragmentation)801 TEST_F(ClatdTest, Fragmentation) {
802 // This test uses hardcoded packets so the clatd address must be fixed.
803 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
804
805 check_fragment_translation(kIPv4Fragments, kIPv4FragLengths, kIPv6Fragments, kIPv6FragLengths,
806 ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
807
808 check_fragment_translation(kIPv6Fragments, kIPv6FragLengths, kIPv4Fragments, kIPv4FragLengths,
809 ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
810 }
811
812 // picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix
gen_random_iid(struct in6_addr * myaddr,struct in_addr * ipv4_local_subnet,struct in6_addr * plat_subnet)813 void gen_random_iid(struct in6_addr *myaddr, struct in_addr *ipv4_local_subnet,
814 struct in6_addr *plat_subnet) {
815 // Fill last 8 bytes of IPv6 address with random bits.
816 arc4random_buf(&myaddr->s6_addr[8], 8);
817
818 // Make the IID checksum-neutral. That is, make it so that:
819 // checksum(Local IPv4 | Remote IPv4) = checksum(Local IPv6 | Remote IPv6)
820 // in other words (because remote IPv6 = NAT64 prefix | Remote IPv4):
821 // checksum(Local IPv4) = checksum(Local IPv6 | NAT64 prefix)
822 // Do this by adjusting the two bytes in the middle of the IID.
823
824 uint16_t middlebytes = (myaddr->s6_addr[11] << 8) + myaddr->s6_addr[12];
825
826 uint32_t c1 = ip_checksum_add(0, ipv4_local_subnet, sizeof(*ipv4_local_subnet));
827 uint32_t c2 = ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
828 ip_checksum_add(0, myaddr, sizeof(*myaddr));
829
830 uint16_t delta = ip_checksum_adjust(middlebytes, c1, c2);
831 myaddr->s6_addr[11] = delta >> 8;
832 myaddr->s6_addr[12] = delta & 0xff;
833 }
834
check_translate_checksum_neutral(const uint8_t * original,size_t original_len,size_t expected_len,const char * msg)835 void check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
836 size_t expected_len, const char *msg) {
837 uint8_t translated[MAXMTU];
838 size_t translated_len = sizeof(translated);
839 do_translate_packet(original, original_len, translated, &translated_len, msg);
840 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
841 // do_translate_packet already checks packets for validity and verifies the checksum.
842 int original_check = get_transport_checksum(original);
843 int translated_check = get_transport_checksum(translated);
844 ASSERT_NE(-1, original_check);
845 ASSERT_NE(-1, translated_check);
846 ASSERT_EQ(original_check, translated_check)
847 << "Not checksum neutral: original and translated checksums differ\n";
848 }
849
TEST_F(ClatdTest,TranslateChecksumNeutral)850 TEST_F(ClatdTest, TranslateChecksumNeutral) {
851 // Generate a random clat IPv6 address and check that translation is checksum-neutral.
852 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
853 &Global_Clatd_Config.ipv6_local_subnet));
854
855 gen_random_iid(&Global_Clatd_Config.ipv6_local_subnet, &Global_Clatd_Config.ipv4_local_subnet,
856 &Global_Clatd_Config.plat_subnet);
857
858 ASSERT_NE(htonl((uint32_t)0x00000464), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
859 ASSERT_NE((uint32_t)0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
860
861 // Check that translating UDP packets is checksum-neutral. First, IPv4.
862 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
863 fix_udp_checksum(udp_ipv4);
864 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
865 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
866
867 // Now try IPv6.
868 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
869 // The test packet uses the static IID, not the random IID. Fix up the source address.
870 struct ip6_hdr *ip6 = (struct ip6_hdr *)udp_ipv6;
871 memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
872 fix_udp_checksum(udp_ipv6);
873 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
874 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
875 }
876
TEST_F(ClatdTest,GetInterfaceIp)877 TEST_F(ClatdTest, GetInterfaceIp) {
878 union anyip *ip = getinterface_ip(sTun.name().c_str(), AF_INET6);
879 ASSERT_NE(nullptr, ip);
880 in6_addr expected = sTun.srcAddr();
881 in6_addr actual = ip->ip6;
882 expect_ipv6_addr_equal(&expected, &actual);
883 }
884
expectSocketBound(int ifindex,int sock)885 void expectSocketBound(int ifindex, int sock) {
886 // Check that the packet socket is bound to the interface. We can't check the socket filter
887 // because there is no way to fetch it from the kernel.
888 sockaddr_ll sll;
889 socklen_t len = sizeof(sll);
890 ASSERT_EQ(0, getsockname(sock, reinterpret_cast<sockaddr *>(&sll), &len));
891 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
892 EXPECT_EQ(ifindex, sll.sll_ifindex);
893 }
894
TEST_F(ClatdTest,ConfigureIpv6Address)895 TEST_F(ClatdTest, ConfigureIpv6Address) {
896 struct tun_data tunnel = makeTunData();
897
898 ASSERT_TRUE(IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_local_subnet));
899
900 const char *addrStr = "2001:db8::f00";
901 in6_addr addr;
902 ASSERT_EQ(1, inet_pton(AF_INET6, addrStr, &addr));
903 ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, sTun.name().c_str(), addrStr));
904
905 EXPECT_EQ(htonl(0x20010db8), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[0]);
906 EXPECT_EQ(htonl(0x00000000), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[1]);
907 EXPECT_EQ(htonl(0x00000000), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[2]);
908 EXPECT_EQ(htonl(0x00000f00), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
909
910 // Check that the packet socket is bound to the interface. We can't check the socket filter
911 // because there is no way to fetch it from the kernel.
912 sockaddr_ll sll;
913 socklen_t len = sizeof(sll);
914 ASSERT_EQ(0, getsockname(tunnel.read_fd6, reinterpret_cast<sockaddr *>(&sll), &len));
915 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
916 EXPECT_EQ(sll.sll_ifindex, sTun.ifindex());
917
918 expectSocketBound(sTun.ifindex(), tunnel.read_fd6);
919
920 freeTunData(&tunnel);
921 }
922
TEST_F(ClatdTest,Ipv6AddressChanged)923 TEST_F(ClatdTest, Ipv6AddressChanged) {
924 // Configure the clat IPv6 address.
925 struct tun_data tunnel = {
926 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
927 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
928 };
929 const char *ifname = sTun.name().c_str();
930
931 in6_addr myaddr = sTun.srcAddr();
932 gen_random_iid(&myaddr, &Global_Clatd_Config.ipv4_local_subnet, &Global_Clatd_Config.plat_subnet);
933 char addrstr[INET6_ADDRSTRLEN];
934 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &myaddr, addrstr, sizeof(addrstr)));
935
936 ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, ifname, addrstr));
937 EXPECT_EQ(0, ipv6_address_changed(ifname));
938 EXPECT_EQ(0, ipv6_address_changed(ifname));
939
940 // Change the IP address on the tun interface to a new prefix.
941 char srcaddr[INET6_ADDRSTRLEN];
942 char dstaddr[INET6_ADDRSTRLEN];
943 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.srcAddr(), srcaddr, sizeof(srcaddr)));
944 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.dstAddr(), dstaddr, sizeof(dstaddr)));
945 EXPECT_EQ(0, ifc_del_address(ifname, srcaddr, 64));
946 EXPECT_EQ(0, ifc_del_address(ifname, dstaddr, 64));
947
948 // Check that we can tell that the address has changed.
949 EXPECT_EQ(0, ifc_add_address(ifname, "2001:db8::1:2", 64));
950 EXPECT_EQ(1, ipv6_address_changed(ifname));
951 EXPECT_EQ(1, ipv6_address_changed(ifname));
952
953 // Restore the tun interface configuration.
954 sTun.destroy();
955 ASSERT_EQ(0, sTun.init());
956 }
957