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