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        snprintf(expected_hexdump + pos, hexdump_len - pos, "\n   ");
383        snprintf(actual_hexdump + pos, hexdump_len - pos, "\n   ");
384        pos += 4;
385      }
386      snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *) expected)[i]);
387      snprintf(actual_hexdump + pos, hexdump_len - 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
436  char foo[512];
437  snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg);
438  check_packet(original, original_len, foo);
439
440  int read_fd, write_fd;
441  uint16_t expected_proto;
442  int version = ip_version(original);
443  switch (version) {
444    case 4:
445      expected_proto = htons(ETH_P_IPV6);
446      read_fd = fds[1];
447      write_fd = fds[0];
448      break;
449    case 6:
450      expected_proto = htons(ETH_P_IP);
451      read_fd = fds[0];
452      write_fd = fds[1];
453      break;
454    default:
455      FAIL() << msg << ": Unsupported IP version " << version << "\n";
456      break;
457  }
458
459  translate_packet(write_fd, (version == 4), original, original_len);
460
461  snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
462  if (version == 6) {
463    // Translating to IPv4. Expect a tun header.
464    struct tun_pi new_tun_header;
465    struct iovec iov[] = {
466      { &new_tun_header, sizeof(new_tun_header) },
467      { out, *outlen }
468    };
469    int len = readv(read_fd, iov, 2);
470    if (len > (int) sizeof(new_tun_header)) {
471      ASSERT_LT((size_t) len, *outlen) << msg << ": Translated packet buffer too small\n";
472      EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
473      *outlen = len - sizeof(new_tun_header);
474      check_packet(out, *outlen, msg);
475    } else {
476      FAIL() << msg << ": Packet was not translated: len=" << len;
477      *outlen = 0;
478    }
479  } else {
480    // Translating to IPv6. Expect raw packet.
481    *outlen = read(read_fd, out, *outlen);
482    check_packet(out, *outlen, msg);
483  }
484}
485
486void check_translated_packet(const uint8_t *original, size_t original_len,
487                             const uint8_t *expected, size_t expected_len, const char *msg) {
488  uint8_t translated[MAXMTU];
489  size_t translated_len = sizeof(translated);
490  do_translate_packet(original, original_len, translated, &translated_len, msg);
491  EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
492  check_data_matches(expected, translated, translated_len, msg);
493}
494
495void check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
496                                const uint8_t *expected[], const size_t expected_lengths[],
497                                int numfragments, const char *msg) {
498  for (int i = 0; i < numfragments; i++) {
499    // Check that each of the fragments translates as expected.
500    char frag_msg[512];
501    snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
502    check_translated_packet(original[i], original_lengths[i],
503                            expected[i], expected_lengths[i], frag_msg);
504  }
505
506  // Sanity check that reassembling the original and translated fragments produces valid packets.
507  uint8_t reassembled[MAXMTU];
508  size_t reassembled_len = sizeof(reassembled);
509  reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
510  check_packet(reassembled, reassembled_len, msg);
511
512  uint8_t translated[MAXMTU];
513  size_t translated_len = sizeof(translated);
514  do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
515  check_packet(translated, translated_len, msg);
516}
517
518int get_transport_checksum(const uint8_t *packet) {
519  struct iphdr *ip;
520  struct ip6_hdr *ip6;
521  uint8_t protocol;
522  const void *payload;
523
524  int version = ip_version(packet);
525  switch (version) {
526    case 4:
527      ip = (struct iphdr *) packet;
528      if (is_ipv4_fragment(ip)) {
529          return -1;
530      }
531      protocol = ip->protocol;
532      payload = ip + 1;
533      break;
534    case 6:
535      ip6 = (struct ip6_hdr *) packet;
536      protocol = ip6->ip6_nxt;
537      payload = ip6 + 1;
538      break;
539    default:
540      return -1;
541  }
542
543  switch (protocol) {
544    case IPPROTO_UDP:
545      return ((struct udphdr *) payload)->check;
546
547    case IPPROTO_TCP:
548      return ((struct tcphdr *) payload)->check;
549
550    case IPPROTO_FRAGMENT:
551    default:
552      return -1;
553  }
554}
555
556struct clat_config Global_Clatd_Config;
557
558class ClatdTest : public ::testing::Test {
559 protected:
560  virtual void SetUp() {
561    inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
562    inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
563    inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
564    Global_Clatd_Config.ipv6_host_id = in6addr_any;
565    Global_Clatd_Config.use_dynamic_iid = 1;
566  }
567};
568
569void expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
570  if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
571    char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
572    inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
573    inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
574    FAIL()
575        << "Unexpected IPv6 address:: "
576        << "\n  Expected: " << expected_str
577        << "\n  Actual:   " << actual_str
578        << "\n";
579  }
580}
581
582TEST_F(ClatdTest, TestIPv6PrefixEqual) {
583  EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
584                                &Global_Clatd_Config.plat_subnet));
585  EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
586                                 &Global_Clatd_Config.ipv6_local_subnet));
587
588  struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
589  EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
590  EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
591
592  subnet2.s6_addr[6] = 0xff;
593  EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
594  EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
595}
596
597int count_onebits(const void *data, size_t size) {
598  int onebits = 0;
599  for (size_t pos = 0; pos < size; pos++) {
600    uint8_t *byte = ((uint8_t*) data) + pos;
601    for (int shift = 0; shift < 8; shift++) {
602      onebits += (*byte >> shift) & 1;
603    }
604  }
605  return onebits;
606}
607
608TEST_F(ClatdTest, TestCountOnebits) {
609  uint64_t i;
610  i = 1;
611  ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
612  i <<= 61;
613  ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
614  i |= ((uint64_t) 1 << 33);
615  ASSERT_EQ(2, count_onebits(&i, sizeof(i)));
616  i = 0xf1000202020000f0;
617  ASSERT_EQ(5 + 1 + 1 + 1 + 4, count_onebits(&i, sizeof(i)));
618}
619
620TEST_F(ClatdTest, TestGenIIDConfigured) {
621  struct in6_addr myaddr, expected;
622  Global_Clatd_Config.use_dynamic_iid = 0;
623  ASSERT_TRUE(inet_pton(AF_INET6, "::bad:ace:d00d", &Global_Clatd_Config.ipv6_host_id));
624  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:0:bad:ace:d00d", &expected));
625  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &myaddr));
626  config_generate_local_ipv6_subnet(&myaddr);
627  expect_ipv6_addr_equal(&expected, &myaddr);
628
629  Global_Clatd_Config.use_dynamic_iid = 1;
630  config_generate_local_ipv6_subnet(&myaddr);
631  EXPECT_FALSE(IN6_ARE_ADDR_EQUAL(&expected, &myaddr));
632}
633
634TEST_F(ClatdTest, TestGenIIDRandom) {
635  struct in6_addr interface_ipv6;
636  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &interface_ipv6));
637  Global_Clatd_Config.ipv6_host_id = in6addr_any;
638
639  // Generate a boatload of random IIDs.
640  int onebits = 0;
641  uint64_t prev_iid = 0;
642  for (int i = 0; i < 100000; i++) {
643    struct in6_addr myaddr =  interface_ipv6;
644
645    config_generate_local_ipv6_subnet(&myaddr);
646
647    // Check the generated IP address is in the same prefix as the interface IPv6 address.
648    EXPECT_TRUE(ipv6_prefix_equal(&interface_ipv6, &myaddr));
649
650    // Check that consecutive IIDs are not the same.
651    uint64_t iid = * (uint64_t*) (&myaddr.s6_addr[8]);
652    ASSERT_TRUE(iid != prev_iid)
653        << "Two consecutive random IIDs are the same: "
654        << std::showbase << std::hex
655        << iid << "\n";
656    prev_iid = iid;
657
658    // Check that the IID is checksum-neutral with the NAT64 prefix and the
659    // local prefix.
660    struct in_addr *ipv4addr = &Global_Clatd_Config.ipv4_local_subnet;
661    struct in6_addr *plat_subnet = &Global_Clatd_Config.plat_subnet;
662
663    uint16_t c1 = ip_checksum_finish(ip_checksum_add(0, ipv4addr, sizeof(*ipv4addr)));
664    uint16_t c2 = ip_checksum_finish(ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
665                                     ip_checksum_add(0, &myaddr, sizeof(myaddr)));
666
667    if (c1 != c2) {
668      char myaddr_str[INET6_ADDRSTRLEN], plat_str[INET6_ADDRSTRLEN], ipv4_str[INET6_ADDRSTRLEN];
669      inet_ntop(AF_INET6, &myaddr, myaddr_str, sizeof(myaddr_str));
670      inet_ntop(AF_INET6, plat_subnet, plat_str, sizeof(plat_str));
671      inet_ntop(AF_INET, ipv4addr, ipv4_str, sizeof(ipv4_str));
672      FAIL()
673          << "Bad IID: " << myaddr_str
674          << " not checksum-neutral with " << ipv4_str << " and " << plat_str
675          << std::showbase << std::hex
676          << "\n  IPv4 checksum: " << c1
677          << "\n  IPv6 checksum: " << c2
678          << "\n";
679    }
680
681    // Check that IIDs are roughly random and use all the bits by counting the
682    // total number of bits set to 1 in a random sample of 100000 generated IIDs.
683    onebits += count_onebits(&iid, sizeof(iid));
684  }
685  EXPECT_LE(3190000, onebits);
686  EXPECT_GE(3210000, onebits);
687}
688
689extern "C" addr_free_func config_is_ipv4_address_free;
690int never_free(in_addr_t /* addr */) { return 0; }
691int always_free(in_addr_t /* addr */) { return 1; }
692int only2_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 2; }
693int over6_free(in_addr_t addr) { return (ntohl(addr) & 0xff) >= 6; }
694int only10_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; }
695
696TEST_F(ClatdTest, SelectIPv4Address) {
697  struct in_addr addr;
698
699  inet_pton(AF_INET, kIPv4LocalAddr, &addr);
700
701  addr_free_func orig_config_is_ipv4_address_free = config_is_ipv4_address_free;
702
703  // If no addresses are free, return INADDR_NONE.
704  config_is_ipv4_address_free = never_free;
705  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
706  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 16));
707
708  // If the configured address is free, pick that. But a prefix that's too big is invalid.
709  config_is_ipv4_address_free = always_free;
710  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 29));
711  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 20));
712  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 15));
713
714  // A prefix length of 32 works, but anything above it is invalid.
715  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 32));
716  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 33));
717
718  // If another address is free, pick it.
719  config_is_ipv4_address_free = over6_free;
720  EXPECT_EQ(inet_addr("192.0.0.6"), config_select_ipv4_address(&addr, 29));
721
722  // Check that we wrap around to addresses that are lower than the first address.
723  config_is_ipv4_address_free = only2_free;
724  EXPECT_EQ(inet_addr("192.0.0.2"), config_select_ipv4_address(&addr, 29));
725  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 30));
726
727  // If a free address exists outside the prefix, we don't pick it.
728  config_is_ipv4_address_free = only10_free;
729  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
730  EXPECT_EQ(inet_addr("192.0.0.10"), config_select_ipv4_address(&addr, 24));
731
732  // Now try using the real function which sees if IP addresses are free using bind().
733  // Assume that the machine running the test has the address 127.0.0.1, but not 8.8.8.8.
734  config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
735  addr.s_addr = inet_addr("8.8.8.8");
736  EXPECT_EQ(inet_addr("8.8.8.8"), config_select_ipv4_address(&addr, 29));
737
738  addr.s_addr = inet_addr("127.0.0.1");
739  EXPECT_EQ(inet_addr("127.0.0.2"), config_select_ipv4_address(&addr, 29));
740}
741
742TEST_F(ClatdTest, DataSanitycheck) {
743  // Sanity checks the data.
744  uint8_t v4_header[] = { IPV4_UDP_HEADER };
745  ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
746
747  uint8_t v6_header[] = { IPV6_UDP_HEADER };
748  ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
749
750  uint8_t udp_header[] = { UDP_HEADER };
751  ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
752
753  // Sanity checks check_packet.
754  struct udphdr *udp;
755  uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
756  udp = (struct udphdr *) (v4_udp_packet + sizeof(struct iphdr));
757  fix_udp_checksum(v4_udp_packet);
758  ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
759  check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
760
761  uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
762  udp = (struct udphdr *) (v6_udp_packet + sizeof(struct ip6_hdr));
763  fix_udp_checksum(v6_udp_packet);
764  ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
765  check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
766
767  uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
768  check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
769
770  uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
771  check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
772
773  // Sanity checks reassemble_packet.
774  uint8_t reassembled[MAXMTU];
775  size_t total_length = sizeof(reassembled);
776  reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments),
777                    reassembled, &total_length, "Reassembly sanity check");
778  check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
779  ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
780  ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *) reassembled))
781      << "Sanity check: reassembled packet is a fragment!\n";
782  check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
783
784  total_length = sizeof(reassembled);
785  reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments),
786                    reassembled, &total_length, "IPv6 reassembly sanity check");
787  ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *) reassembled, total_length))
788      << "Sanity check: reassembled packet is a fragment!\n";
789  check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
790}
791
792TEST_F(ClatdTest, PseudoChecksum) {
793  uint32_t pseudo_checksum;
794
795  uint8_t v4_header[] = { IPV4_UDP_HEADER };
796  uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
797  pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *) v4_header, UDP_LEN);
798  EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
799            ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
800            << "ipv4_pseudo_header_checksum incorrect\n";
801
802  uint8_t v6_header[] = { IPV6_UDP_HEADER };
803  uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
804  pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *) v6_header, UDP_LEN, IPPROTO_UDP);
805  EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
806            ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
807            << "ipv6_pseudo_header_checksum incorrect\n";
808}
809
810TEST_F(ClatdTest, TransportChecksum) {
811  uint8_t udphdr[] = { UDP_HEADER };
812  uint8_t payload[] = { PAYLOAD };
813  EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
814            << "UDP partial checksum\n";
815  EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
816            << "Payload partial checksum\n";
817
818  uint8_t ip[] = { IPV4_UDP_HEADER };
819  uint8_t ip6[] = { IPV6_UDP_HEADER };
820  uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *) ip, UDP_LEN);
821  uint32_t ipv6_pseudo_sum = ipv6_pseudo_header_checksum((struct ip6_hdr *) ip6, UDP_LEN,
822                                                         IPPROTO_UDP);
823
824  EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum) << "IPv4 pseudo-checksum sanity check\n";
825  EXPECT_EQ(0x2644bU, ipv6_pseudo_sum) << "IPv6 pseudo-checksum sanity check\n";
826  EXPECT_EQ(
827      kUdpV4Checksum,
828      ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
829      << "Unexpected UDP/IPv4 checksum\n";
830  EXPECT_EQ(
831      kUdpV6Checksum,
832      ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
833      << "Unexpected UDP/IPv6 checksum\n";
834
835  EXPECT_EQ(kUdpV6Checksum,
836      ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
837      << "Adjust IPv4/UDP checksum to IPv6\n";
838  EXPECT_EQ(kUdpV4Checksum,
839      ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
840      << "Adjust IPv6/UDP checksum to IPv4\n";
841}
842
843TEST_F(ClatdTest, AdjustChecksum) {
844  struct checksum_data {
845    uint16_t checksum;
846    uint32_t old_hdr_sum;
847    uint32_t new_hdr_sum;
848    uint16_t result;
849  } DATA[] = {
850    { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
851    { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
852    { 0xdd2f, 0x5555, 0x3285, 0x0000 },
853    { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
854    { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
855  };
856  unsigned i = 0;
857
858  for (i = 0; i < ARRAYSIZE(DATA); i++) {
859    struct checksum_data *data = DATA + i;
860    uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
861    EXPECT_EQ(result, data->result)
862        << "Incorrect checksum" << std::showbase << std::hex
863        << "\n  Expected: " << data->result
864        << "\n  Actual:   " << result
865        << "\n    checksum=" << data->checksum
866        << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
867  }
868}
869
870TEST_F(ClatdTest, Translate) {
871  uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
872  uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
873  fix_udp_checksum(udp_ipv4);
874  fix_udp_checksum(udp_ipv6);
875  check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
876                          "UDP/IPv4 -> UDP/IPv6 translation");
877  check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
878                          "UDP/IPv6 -> UDP/IPv4 translation");
879
880  uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
881  uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
882  check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
883                          "ICMP->ICMPv6 translation");
884  check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
885                          "ICMPv6->ICMP translation");
886}
887
888TEST_F(ClatdTest, Fragmentation) {
889  check_fragment_translation(kIPv4Fragments, kIPv4FragLengths,
890                             kIPv6Fragments, kIPv6FragLengths,
891                             ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
892
893  check_fragment_translation(kIPv6Fragments, kIPv6FragLengths,
894                             kIPv4Fragments, kIPv4FragLengths,
895                             ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
896}
897
898void check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
899                                      size_t expected_len, const char *msg) {
900  uint8_t translated[MAXMTU];
901  size_t translated_len = sizeof(translated);
902  do_translate_packet(original, original_len, translated, &translated_len, msg);
903  EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
904  // do_translate_packet already checks packets for validity and verifies the checksum.
905  int original_check = get_transport_checksum(original);
906  int translated_check = get_transport_checksum(translated);
907  ASSERT_NE(-1, original_check);
908  ASSERT_NE(-1, translated_check);
909  ASSERT_EQ(original_check, translated_check)
910      << "Not checksum neutral: original and translated checksums differ\n";
911}
912
913TEST_F(ClatdTest, TranslateChecksumNeutral) {
914  // Generate a random clat IPv6 address and check that translation is checksum-neutral.
915  Global_Clatd_Config.ipv6_host_id = in6addr_any;
916  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
917                        &Global_Clatd_Config.ipv6_local_subnet));
918  config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet);
919  ASSERT_NE((uint32_t) 0x00000464, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
920  ASSERT_NE((uint32_t) 0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
921
922  // Check that translating UDP packets is checksum-neutral. First, IPv4.
923  uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
924  fix_udp_checksum(udp_ipv4);
925  check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
926                                   "UDP/IPv4 -> UDP/IPv6 checksum neutral");
927
928  // Now try IPv6.
929  uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
930  // The test packet uses the static IID, not the random IID. Fix up the source address.
931  struct ip6_hdr *ip6 = (struct ip6_hdr *) udp_ipv6;
932  memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
933  fix_udp_checksum(udp_ipv6);
934  check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
935                                   "UDP/IPv4 -> UDP/IPv6 checksum neutral");
936}
937