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
28extern "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.
39static const char kIPv4LocalAddr[] = "192.0.0.4";
40static const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
41static 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.
105static 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};
111static 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};
117static 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};
122static const uint8_t *kIPv4Fragments[] = { kIPv4Frag1, kIPv4Frag2, kIPv4Frag3 };
123static const size_t kIPv4FragLengths[] = { sizeof(kIPv4Frag1), sizeof(kIPv4Frag2),
124                                           sizeof(kIPv4Frag3) };
125
126static 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
136static 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
146static 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};
154static const uint8_t *kIPv6Fragments[] = { kIPv6Frag1, kIPv6Frag2, kIPv6Frag3 };
155static const size_t kIPv6FragLengths[] = { sizeof(kIPv6Frag1), sizeof(kIPv6Frag2),
156                                           sizeof(kIPv6Frag3) };
157
158static 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.
169static const uint32_t kUdpPartialChecksum     = 0xd5c8;
170static const uint32_t kPayloadPartialChecksum = 0x31e9c;
171static const uint16_t kUdpV4Checksum          = 0xd0c7;
172static const uint16_t kUdpV6Checksum          = 0xa74a;
173
174uint8_t ip_version(const uint8_t *packet) {
175  uint8_t version = packet[0] >> 4;
176  return version;
177}
178
179int 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
184int 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
193int ipv4_fragment_offset(struct iphdr *ip) {
194  return ntohs(ip->frag_off) & IP_OFFMASK;
195}
196
197int ipv6_fragment_offset(struct ip6_frag *frag) {
198  return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3);
199}
200
201void 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
286void 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
374void 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
396void 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.
425extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) {
426    writev(fd, out, iov_len);
427}
428
429void 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
489void 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
498void 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
521int 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
559struct clat_config Global_Clatd_Config;
560
561class 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
572void 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
585TEST_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
600int 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
611TEST_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
623TEST_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
637TEST_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
692extern "C" addr_free_func config_is_ipv4_address_free;
693int never_free(in_addr_t /* addr */) { return 0; }
694int always_free(in_addr_t /* addr */) { return 1; }
695int only2_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 2; }
696int over6_free(in_addr_t addr) { return (ntohl(addr) & 0xff) >= 6; }
697int only10_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; }
698
699TEST_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
745TEST_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
795TEST_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
813TEST_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
846TEST_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
873TEST_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
891TEST_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
902void 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
917TEST_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