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 
ip_version(const uint8_t * packet)174 uint8_t ip_version(const uint8_t *packet) {
175   uint8_t version = packet[0] >> 4;
176   return version;
177 }
178 
is_ipv4_fragment(struct iphdr * ip)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 
is_ipv6_fragment(struct ip6_hdr * ip6,size_t len)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 
ipv4_fragment_offset(struct iphdr * ip)193 int ipv4_fragment_offset(struct iphdr *ip) {
194   return ntohs(ip->frag_off) & IP_OFFMASK;
195 }
196 
ipv6_fragment_offset(struct ip6_frag * frag)197 int ipv6_fragment_offset(struct ip6_frag *frag) {
198   return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3);
199 }
200 
check_packet(const uint8_t * packet,size_t len,const char * msg)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 
reassemble_packet(const uint8_t ** fragments,const size_t lengths[],int numpackets,uint8_t * reassembled,size_t * reassembled_len,const char * msg)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 
check_data_matches(const void * expected,const void * actual,size_t len,const char * msg)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 
fix_udp_checksum(uint8_t * packet)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.
send_rawv6(int fd,clat_packet out,int iov_len)425 extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) {
426     writev(fd, out, iov_len);
427 }
428 
do_translate_packet(const uint8_t * original,size_t original_len,uint8_t * out,size_t * outlen,const char * msg)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 
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 
check_translated_packet(const uint8_t * original,size_t original_len,const uint8_t * expected,size_t expected_len,const char * msg)486 void 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 
check_fragment_translation(const uint8_t * original[],const size_t original_lengths[],const uint8_t * expected[],const size_t expected_lengths[],int numfragments,const char * msg)495 void 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 
get_transport_checksum(const uint8_t * packet)518 int 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 
556 struct clat_config Global_Clatd_Config;
557 
558 class ClatdTest : public ::testing::Test {
559  protected:
SetUp()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 
expect_ipv6_addr_equal(struct in6_addr * expected,struct in6_addr * actual)569 void 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 
TEST_F(ClatdTest,TestIPv6PrefixEqual)582 TEST_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 
count_onebits(const void * data,size_t size)597 int 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 
TEST_F(ClatdTest,TestCountOnebits)608 TEST_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 
TEST_F(ClatdTest,TestGenIIDConfigured)620 TEST_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 
TEST_F(ClatdTest,TestGenIIDRandom)634 TEST_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 
689 extern "C" addr_free_func config_is_ipv4_address_free;
never_free(in_addr_t)690 int never_free(in_addr_t /* addr */) { return 0; }
always_free(in_addr_t)691 int always_free(in_addr_t /* addr */) { return 1; }
only2_free(in_addr_t addr)692 int only2_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 2; }
over6_free(in_addr_t addr)693 int over6_free(in_addr_t addr) { return (ntohl(addr) & 0xff) >= 6; }
only10_free(in_addr_t addr)694 int only10_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; }
695 
TEST_F(ClatdTest,SelectIPv4Address)696 TEST_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 
TEST_F(ClatdTest,DataSanitycheck)742 TEST_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 
TEST_F(ClatdTest,PseudoChecksum)792 TEST_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 
TEST_F(ClatdTest,TransportChecksum)810 TEST_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 
TEST_F(ClatdTest,AdjustChecksum)843 TEST_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 
TEST_F(ClatdTest,Translate)870 TEST_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 
TEST_F(ClatdTest,Fragmentation)888 TEST_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 
check_translate_checksum_neutral(const uint8_t * original,size_t original_len,size_t expected_len,const char * msg)898 void 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 
TEST_F(ClatdTest,TranslateChecksumNeutral)913 TEST_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