blob: c16a4dd783ff12e8b80bb43a284549d8ef67ecc9 [file] [log] [blame]
Lorenzo Colittif3beefc2014-02-14 13:19:27 +09001/*
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
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090021#include <arpa/inet.h>
Lorenzo Colitti98089522014-10-09 22:29:45 +090022#include <netinet/in6.h>
junyulaic4e591a2018-11-26 22:36:10 +090023#include <stdio.h>
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090024#include <sys/uio.h>
25
26#include <gtest/gtest.h>
Lorenzo Colitti66deecd2019-01-04 12:27:27 +090027
28#include "netutils/ifc.h"
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090029#include "tun_interface.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090030
31extern "C" {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090032#include "clatd.h"
junyulaic4e591a2018-11-26 22:36:10 +090033#include "config.h"
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090034#include "getaddr.h"
Lorenzo Colitti98de5952019-01-20 11:45:03 +090035#include "netutils/checksum.h"
junyulaic4e591a2018-11-26 22:36:10 +090036#include "translate.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090037}
38
39// For convenience.
40#define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0])
41
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090042using android::net::TunInterface;
43
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090044// Default translation parameters.
junyulaic4e591a2018-11-26 22:36:10 +090045static const char kIPv4LocalAddr[] = "192.0.0.4";
46static const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090047static const char kIPv6PlatSubnet[] = "64:ff9b::";
48
junyulaic4e591a2018-11-26 22:36:10 +090049// clang-format off
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090050// Test packet portions. Defined as macros because it's easy to concatenate them to make packets.
51#define IPV4_HEADER(p, c1, c2) \
52 0x45, 0x00, 0, 41, /* Version=4, IHL=5, ToS=0x80, len=41 */ \
53 0x00, 0x00, 0x40, 0x00, /* ID=0x0000, flags=IP_DF, offset=0 */ \
54 55, (p), (c1), (c2), /* TTL=55, protocol=p, checksum=c1,c2 */ \
55 192, 0, 0, 4, /* Src=192.0.0.4 */ \
56 8, 8, 8, 8, /* Dst=8.8.8.8 */
57#define IPV4_UDP_HEADER IPV4_HEADER(IPPROTO_UDP, 0x73, 0xb0)
58#define IPV4_ICMP_HEADER IPV4_HEADER(IPPROTO_ICMP, 0x73, 0xc0)
59
60#define IPV6_HEADER(p) \
61 0x60, 0x00, 0, 0, /* Version=6, tclass=0x00, flowlabel=0 */ \
62 0, 21, (p), 55, /* plen=11, nxthdr=p, hlim=55 */ \
63 0x20, 0x01, 0x0d, 0xb8, /* Src=2001:db8:0:b11::464 */ \
64 0x00, 0x00, 0x0b, 0x11, \
65 0x00, 0x00, 0x00, 0x00, \
66 0x00, 0x00, 0x04, 0x64, \
67 0x00, 0x64, 0xff, 0x9b, /* Dst=64:ff9b::8.8.8.8 */ \
68 0x00, 0x00, 0x00, 0x00, \
69 0x00, 0x00, 0x00, 0x00, \
70 0x08, 0x08, 0x08, 0x08,
71#define IPV6_UDP_HEADER IPV6_HEADER(IPPROTO_UDP)
72#define IPV6_ICMPV6_HEADER IPV6_HEADER(IPPROTO_ICMPV6)
73
74#define UDP_LEN 21
75#define UDP_HEADER \
76 0xc8, 0x8b, 0, 53, /* Port 51339->53 */ \
77 0x00, UDP_LEN, 0, 0, /* Length 21, checksum empty for now */
78
79#define PAYLOAD 'H', 'e', 'l', 'l', 'o', ' ', 0x4e, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0x00
80
81#define IPV4_PING \
82 0x08, 0x00, 0x88, 0xd0, /* Type 8, code 0, checksum 0x88d0 */ \
83 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
84
85#define IPV6_PING \
86 0x80, 0x00, 0xc3, 0x42, /* Type 128, code 0, checksum 0xc342 */ \
87 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
88
89// Macros to return pseudo-headers from packets.
90#define IPV4_PSEUDOHEADER(ip, tlen) \
91 ip[12], ip[13], ip[14], ip[15], /* Source address */ \
92 ip[16], ip[17], ip[18], ip[19], /* Destination address */ \
93 0, ip[9], /* 0, protocol */ \
94 ((tlen) >> 16) & 0xff, (tlen) & 0xff, /* Transport length */
95
96#define IPV6_PSEUDOHEADER(ip6, protocol, tlen) \
97 ip6[8], ip6[9], ip6[10], ip6[11], /* Source address */ \
98 ip6[12], ip6[13], ip6[14], ip6[15], \
99 ip6[16], ip6[17], ip6[18], ip6[19], \
100 ip6[20], ip6[21], ip6[22], ip6[23], \
101 ip6[24], ip6[25], ip6[26], ip6[27], /* Destination address */ \
102 ip6[28], ip6[29], ip6[30], ip6[31], \
103 ip6[32], ip6[33], ip6[34], ip6[35], \
104 ip6[36], ip6[37], ip6[38], ip6[39], \
105 ((tlen) >> 24) & 0xff, /* Transport length */ \
106 ((tlen) >> 16) & 0xff, \
107 ((tlen) >> 8) & 0xff, \
108 (tlen) & 0xff, \
109 0, 0, 0, (protocol),
110
111// A fragmented DNS request.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800112static const uint8_t kIPv4Frag1[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900113 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x00, 0x40, 0x11,
114 0x8c, 0x6d, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
115 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
116 0x01, 0x00, 0x00, 0x01, 0x00, 0x00
117};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800118static const uint8_t kIPv4Frag2[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900119 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x02, 0x40, 0x11,
120 0x8c, 0x6b, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
121 0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06,
122 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65
123};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800124static const uint8_t kIPv4Frag3[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900125 0x45, 0x00, 0x00, 0x1d, 0xfe, 0x47, 0x00, 0x04, 0x40, 0x11,
126 0xac, 0x70, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
127 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
128};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800129static const uint8_t *kIPv4Fragments[] = { kIPv4Frag1, kIPv4Frag2, kIPv4Frag3 };
130static const size_t kIPv4FragLengths[] = { sizeof(kIPv4Frag1), sizeof(kIPv4Frag2),
131 sizeof(kIPv4Frag3) };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900132
Brian Carlstromfcac4102014-02-24 20:03:01 -0800133static const uint8_t kIPv6Frag1[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900134 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
135 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
138 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x47, 0x14, 0x5d,
139 0x00, 0x35, 0x00, 0x29, 0xeb, 0x91, 0x50, 0x47, 0x01, 0x00,
140 0x00, 0x01, 0x00, 0x00
141};
142
Brian Carlstromfcac4102014-02-24 20:03:01 -0800143static const uint8_t kIPv6Frag2[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900144 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
145 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
148 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0xfe, 0x47, 0x00, 0x00,
149 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f,
150 0x6f, 0x67, 0x6c, 0x65
151};
152
Brian Carlstromfcac4102014-02-24 20:03:01 -0800153static const uint8_t kIPv6Frag3[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900154 0x60, 0x00, 0x00, 0x00, 0x00, 0x11, 0x2c, 0x40, 0x20, 0x01,
155 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
158 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0xfe, 0x47, 0x03, 0x63,
159 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
160};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800161static const uint8_t *kIPv6Fragments[] = { kIPv6Frag1, kIPv6Frag2, kIPv6Frag3 };
162static const size_t kIPv6FragLengths[] = { sizeof(kIPv6Frag1), sizeof(kIPv6Frag2),
163 sizeof(kIPv6Frag3) };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900164
Brian Carlstromfcac4102014-02-24 20:03:01 -0800165static const uint8_t kReassembledIPv4[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900166 0x45, 0x00, 0x00, 0x3d, 0xfe, 0x47, 0x00, 0x00, 0x40, 0x11,
167 0xac, 0x54, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
168 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
169 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67,
171 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
172 0x01
173};
junyulaic4e591a2018-11-26 22:36:10 +0900174// clang-format on
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900175
176// Expected checksums.
177static const uint32_t kUdpPartialChecksum = 0xd5c8;
178static const uint32_t kPayloadPartialChecksum = 0x31e9c;
179static const uint16_t kUdpV4Checksum = 0xd0c7;
180static const uint16_t kUdpV6Checksum = 0xa74a;
181
Brian Carlstromfcac4102014-02-24 20:03:01 -0800182uint8_t ip_version(const uint8_t *packet) {
183 uint8_t version = packet[0] >> 4;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900184 return version;
185}
186
187int is_ipv4_fragment(struct iphdr *ip) {
188 // A packet is a fragment if its fragment offset is nonzero or if the MF flag is set.
189 return ntohs(ip->frag_off) & (IP_OFFMASK | IP_MF);
190}
191
192int is_ipv6_fragment(struct ip6_hdr *ip6, size_t len) {
193 if (ip6->ip6_nxt != IPPROTO_FRAGMENT) {
194 return 0;
195 }
junyulaic4e591a2018-11-26 22:36:10 +0900196 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900197 return len >= sizeof(*ip6) + sizeof(*frag) &&
junyulaic4e591a2018-11-26 22:36:10 +0900198 (frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900199}
200
201int ipv4_fragment_offset(struct iphdr *ip) {
202 return ntohs(ip->frag_off) & IP_OFFMASK;
203}
204
205int ipv6_fragment_offset(struct ip6_frag *frag) {
206 return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3);
207}
208
Brian Carlstromfcac4102014-02-24 20:03:01 -0800209void check_packet(const uint8_t *packet, size_t len, const char *msg) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900210 void *payload;
junyulaic4e591a2018-11-26 22:36:10 +0900211 size_t payload_length = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900212 uint32_t pseudo_checksum = 0;
junyulaic4e591a2018-11-26 22:36:10 +0900213 uint8_t protocol = 0;
214 int version = ip_version(packet);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900215 switch (version) {
216 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900217 struct iphdr *ip = (struct iphdr *)packet;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900218 ASSERT_GE(len, sizeof(*ip)) << msg << ": IPv4 packet shorter than IPv4 header\n";
219 EXPECT_EQ(5, ip->ihl) << msg << ": Unsupported IP header length\n";
220 EXPECT_EQ(len, ntohs(ip->tot_len)) << msg << ": Incorrect IPv4 length\n";
221 EXPECT_EQ(0, ip_checksum(ip, sizeof(*ip))) << msg << ": Incorrect IP checksum\n";
222 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900223 payload = ip + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900224 if (!is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900225 payload_length = len - sizeof(*ip);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900226 pseudo_checksum = ipv4_pseudo_header_checksum(ip, payload_length);
227 }
228 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP)
junyulaic4e591a2018-11-26 22:36:10 +0900229 << msg << ": Unsupported IPv4 protocol " << protocol << "\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900230 break;
231 }
232 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900233 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900234 ASSERT_GE(len, sizeof(*ip6)) << msg << ": IPv6 packet shorter than IPv6 header\n";
235 EXPECT_EQ(len - sizeof(*ip6), htons(ip6->ip6_plen)) << msg << ": Incorrect IPv6 length\n";
236
237 if (ip6->ip6_nxt == IPPROTO_FRAGMENT) {
junyulaic4e591a2018-11-26 22:36:10 +0900238 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900239 ASSERT_GE(len, sizeof(*ip6) + sizeof(*frag))
junyulaic4e591a2018-11-26 22:36:10 +0900240 << msg << ": IPv6 fragment: short fragment header\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900241 protocol = frag->ip6f_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900242 payload = frag + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900243 // Even though the packet has a Fragment header, it might not be a fragment.
244 if (!is_ipv6_fragment(ip6, len)) {
245 payload_length = len - sizeof(*ip6) - sizeof(*frag);
246 }
247 } else {
248 // Since there are no extension headers except Fragment, this must be the payload.
junyulaic4e591a2018-11-26 22:36:10 +0900249 protocol = ip6->ip6_nxt;
250 payload = ip6 + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900251 payload_length = len - sizeof(*ip6);
252 }
253 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMPV6)
junyulaic4e591a2018-11-26 22:36:10 +0900254 << msg << ": Unsupported IPv6 next header " << protocol;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900255 if (payload_length) {
256 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, payload_length, protocol);
257 }
258 break;
259 }
260 default:
261 FAIL() << msg << ": Unsupported IP version " << version << "\n";
262 return;
263 }
264
265 // If we understand the payload, verify the checksum.
266 if (payload_length) {
267 uint16_t checksum;
junyulaic4e591a2018-11-26 22:36:10 +0900268 switch (protocol) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900269 case IPPROTO_UDP:
270 case IPPROTO_TCP:
271 case IPPROTO_ICMPV6:
272 checksum = ip_checksum_finish(ip_checksum_add(pseudo_checksum, payload, payload_length));
273 break;
274 case IPPROTO_ICMP:
275 checksum = ip_checksum(payload, payload_length);
276 break;
277 default:
278 checksum = 0; // Don't check.
279 break;
280 }
281 EXPECT_EQ(0, checksum) << msg << ": Incorrect transport checksum\n";
282 }
283
284 if (protocol == IPPROTO_UDP) {
junyulaic4e591a2018-11-26 22:36:10 +0900285 struct udphdr *udp = (struct udphdr *)payload;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900286 EXPECT_NE(0, udp->check) << msg << ": UDP checksum 0 should be 0xffff";
287 // If this is not a fragment, check the UDP length field.
288 if (payload_length) {
289 EXPECT_EQ(payload_length, ntohs(udp->len)) << msg << ": Incorrect UDP length\n";
290 }
291 }
292}
293
Brian Carlstromfcac4102014-02-24 20:03:01 -0800294void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int numpackets,
295 uint8_t *reassembled, size_t *reassembled_len, const char *msg) {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900296 struct iphdr *ip = nullptr;
297 struct ip6_hdr *ip6 = nullptr;
junyulaic4e591a2018-11-26 22:36:10 +0900298 size_t total_length, pos = 0;
Ben Cheng932614e2014-04-02 17:00:26 -0700299 uint8_t protocol = 0;
junyulaic4e591a2018-11-26 22:36:10 +0900300 uint8_t version = ip_version(fragments[0]);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900301
302 for (int i = 0; i < numpackets; i++) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800303 const uint8_t *packet = fragments[i];
junyulaic4e591a2018-11-26 22:36:10 +0900304 int len = lengths[i];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900305 int headersize, payload_offset;
306
307 ASSERT_EQ(ip_version(packet), version) << msg << ": Inconsistent fragment versions\n";
308 check_packet(packet, len, "Fragment sanity check");
309
310 switch (version) {
311 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900312 struct iphdr *ip_orig = (struct iphdr *)packet;
313 headersize = sizeof(*ip_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900314 ASSERT_TRUE(is_ipv4_fragment(ip_orig))
junyulaic4e591a2018-11-26 22:36:10 +0900315 << msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n";
316 ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip) : 0))
317 << msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900318
junyulaic4e591a2018-11-26 22:36:10 +0900319 headersize = sizeof(*ip_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900320 payload_offset = headersize;
321 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900322 ip = (struct iphdr *)reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900323 }
324 break;
325 }
326 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900327 struct ip6_hdr *ip6_orig = (struct ip6_hdr *)packet;
328 struct ip6_frag *frag = (struct ip6_frag *)(ip6_orig + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900329 ASSERT_TRUE(is_ipv6_fragment(ip6_orig, len))
junyulaic4e591a2018-11-26 22:36:10 +0900330 << msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n";
331 ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6) : 0))
332 << msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900333
junyulaic4e591a2018-11-26 22:36:10 +0900334 headersize = sizeof(*ip6_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900335 payload_offset = sizeof(*ip6_orig) + sizeof(*frag);
336 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900337 ip6 = (struct ip6_hdr *)reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900338 protocol = frag->ip6f_nxt;
339 }
340 break;
341 }
342 default:
343 FAIL() << msg << ": Invalid IP version << " << version;
344 }
345
346 // If this is the first fragment, copy the header.
347 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900348 ASSERT_LT(headersize, (int)*reassembled_len) << msg << ": Reassembly buffer too small\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900349 memcpy(reassembled, packet, headersize);
350 total_length = headersize;
351 pos += headersize;
352 }
353
354 // Copy the payload.
355 int payload_length = len - payload_offset;
356 total_length += payload_length;
Ben Cheng932614e2014-04-02 17:00:26 -0700357 ASSERT_LT(total_length, *reassembled_len) << msg << ": Reassembly buffer too small\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900358 memcpy(reassembled + pos, packet + payload_offset, payload_length);
359 pos += payload_length;
360 }
361
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900362 // Fix up the reassembled headers to reflect fragmentation and length (and IPv4 checksum).
363 ASSERT_EQ(total_length, pos) << msg << ": Reassembled packet length incorrect\n";
364 if (ip) {
365 ip->frag_off &= ~htons(IP_MF);
366 ip->tot_len = htons(total_length);
junyulaic4e591a2018-11-26 22:36:10 +0900367 ip->check = 0;
368 ip->check = ip_checksum(ip, sizeof(*ip));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900369 ASSERT_FALSE(is_ipv4_fragment(ip)) << msg << ": reassembled IPv4 packet is a fragment!\n";
370 }
371 if (ip6) {
junyulaic4e591a2018-11-26 22:36:10 +0900372 ip6->ip6_nxt = protocol;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900373 ip6->ip6_plen = htons(total_length - sizeof(*ip6));
374 ASSERT_FALSE(is_ipv6_fragment(ip6, ip6->ip6_plen))
junyulaic4e591a2018-11-26 22:36:10 +0900375 << msg << ": reassembled IPv6 packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900376 }
377
378 *reassembled_len = total_length;
379}
380
Lorenzo Colitti98089522014-10-09 22:29:45 +0900381void check_data_matches(const void *expected, const void *actual, size_t len, const char *msg) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900382 if (memcmp(expected, actual, len)) {
383 // Hex dump, 20 bytes per line, one space between bytes (1 byte = 3 chars), indented by 4.
384 int hexdump_len = len * 3 + (len / 20 + 1) * 5;
385 char expected_hexdump[hexdump_len], actual_hexdump[hexdump_len];
386 unsigned pos = 0;
387 for (unsigned i = 0; i < len; i++) {
388 if (i % 20 == 0) {
George Burgess IV2dcca6f2016-02-24 15:55:54 -0800389 snprintf(expected_hexdump + pos, hexdump_len - pos, "\n ");
390 snprintf(actual_hexdump + pos, hexdump_len - pos, "\n ");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900391 pos += 4;
392 }
junyulaic4e591a2018-11-26 22:36:10 +0900393 snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)expected)[i]);
394 snprintf(actual_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)actual)[i]);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900395 pos += 3;
396 }
Lorenzo Colitti98089522014-10-09 22:29:45 +0900397 FAIL() << msg << ": Data doesn't match"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900398 << "\n Expected:" << (char *) expected_hexdump
399 << "\n Actual:" << (char *) actual_hexdump << "\n";
400 }
401}
402
junyulaic4e591a2018-11-26 22:36:10 +0900403void fix_udp_checksum(uint8_t *packet) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900404 uint32_t pseudo_checksum;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800405 uint8_t version = ip_version(packet);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900406 struct udphdr *udp;
407 switch (version) {
408 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900409 struct iphdr *ip = (struct iphdr *)packet;
410 udp = (struct udphdr *)(ip + 1);
411 pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900412 break;
413 }
414 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900415 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
416 udp = (struct udphdr *)(ip6 + 1);
417 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900418 break;
419 }
420 default:
421 FAIL() << "unsupported IP version" << version << "\n";
422 return;
junyulaic4e591a2018-11-26 22:36:10 +0900423 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900424
425 udp->check = 0;
426 udp->check = ip_checksum_finish(ip_checksum_add(pseudo_checksum, udp, ntohs(udp->len)));
427}
428
Lorenzo Colittice140882014-06-02 21:20:40 +0900429// Testing stub for send_rawv6. The real version uses sendmsg() with a
430// destination IPv6 address, and attempting to call that on our test socketpair
431// fd results in EINVAL.
junyulaic4e591a2018-11-26 22:36:10 +0900432extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) { writev(fd, out, iov_len); }
Lorenzo Colittice140882014-06-02 21:20:40 +0900433
Brian Carlstromfcac4102014-02-24 20:03:01 -0800434void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *out, size_t *outlen,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900435 const char *msg) {
436 int fds[2];
437 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, fds)) {
438 abort();
439 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900440
441 char foo[512];
442 snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg);
443 check_packet(original, original_len, foo);
444
Lorenzo Colittie24982e2014-06-02 15:49:36 +0900445 int read_fd, write_fd;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900446 uint16_t expected_proto;
447 int version = ip_version(original);
448 switch (version) {
449 case 4:
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900450 expected_proto = htons(ETH_P_IPV6);
junyulaic4e591a2018-11-26 22:36:10 +0900451 read_fd = fds[1];
452 write_fd = fds[0];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900453 break;
454 case 6:
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900455 expected_proto = htons(ETH_P_IP);
junyulaic4e591a2018-11-26 22:36:10 +0900456 read_fd = fds[0];
457 write_fd = fds[1];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900458 break;
459 default:
460 FAIL() << msg << ": Unsupported IP version " << version << "\n";
461 break;
462 }
463
Lorenzo Colittie24982e2014-06-02 15:49:36 +0900464 translate_packet(write_fd, (version == 4), original, original_len);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900465
Lorenzo Colitti98089522014-10-09 22:29:45 +0900466 snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
Lorenzo Colittice140882014-06-02 21:20:40 +0900467 if (version == 6) {
468 // Translating to IPv4. Expect a tun header.
469 struct tun_pi new_tun_header;
470 struct iovec iov[] = {
471 { &new_tun_header, sizeof(new_tun_header) },
junyulaic4e591a2018-11-26 22:36:10 +0900472 { out, *outlen },
Lorenzo Colittice140882014-06-02 21:20:40 +0900473 };
junyulaic4e591a2018-11-26 22:36:10 +0900474
Lorenzo Colittice140882014-06-02 21:20:40 +0900475 int len = readv(read_fd, iov, 2);
junyulaic4e591a2018-11-26 22:36:10 +0900476 if (len > (int)sizeof(new_tun_header)) {
477 ASSERT_LT((size_t)len, *outlen) << msg << ": Translated packet buffer too small\n";
Lorenzo Colittice140882014-06-02 21:20:40 +0900478 EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
479 *outlen = len - sizeof(new_tun_header);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900480 check_packet(out, *outlen, msg);
Lorenzo Colittice140882014-06-02 21:20:40 +0900481 } else {
Lorenzo Colitti98089522014-10-09 22:29:45 +0900482 FAIL() << msg << ": Packet was not translated: len=" << len;
Lorenzo Colittice140882014-06-02 21:20:40 +0900483 *outlen = 0;
484 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900485 } else {
Lorenzo Colittice140882014-06-02 21:20:40 +0900486 // Translating to IPv6. Expect raw packet.
487 *outlen = read(read_fd, out, *outlen);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900488 check_packet(out, *outlen, msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900489 }
490}
491
junyulaic4e591a2018-11-26 22:36:10 +0900492void check_translated_packet(const uint8_t *original, size_t original_len, const uint8_t *expected,
493 size_t expected_len, const char *msg) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800494 uint8_t translated[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900495 size_t translated_len = sizeof(translated);
496 do_translate_packet(original, original_len, translated, &translated_len, msg);
497 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
498 check_data_matches(expected, translated, translated_len, msg);
499}
500
Brian Carlstromfcac4102014-02-24 20:03:01 -0800501void check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
502 const uint8_t *expected[], const size_t expected_lengths[],
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900503 int numfragments, const char *msg) {
504 for (int i = 0; i < numfragments; i++) {
505 // Check that each of the fragments translates as expected.
506 char frag_msg[512];
507 snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
junyulaic4e591a2018-11-26 22:36:10 +0900508 check_translated_packet(original[i], original_lengths[i], expected[i], expected_lengths[i],
509 frag_msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900510 }
511
512 // Sanity check that reassembling the original and translated fragments produces valid packets.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800513 uint8_t reassembled[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900514 size_t reassembled_len = sizeof(reassembled);
515 reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
516 check_packet(reassembled, reassembled_len, msg);
517
Brian Carlstromfcac4102014-02-24 20:03:01 -0800518 uint8_t translated[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900519 size_t translated_len = sizeof(translated);
520 do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
521 check_packet(translated, translated_len, msg);
522}
523
Lorenzo Colitti98089522014-10-09 22:29:45 +0900524int get_transport_checksum(const uint8_t *packet) {
525 struct iphdr *ip;
526 struct ip6_hdr *ip6;
527 uint8_t protocol;
528 const void *payload;
529
530 int version = ip_version(packet);
531 switch (version) {
532 case 4:
junyulaic4e591a2018-11-26 22:36:10 +0900533 ip = (struct iphdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900534 if (is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900535 return -1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900536 }
537 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900538 payload = ip + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900539 break;
540 case 6:
junyulaic4e591a2018-11-26 22:36:10 +0900541 ip6 = (struct ip6_hdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900542 protocol = ip6->ip6_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900543 payload = ip6 + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900544 break;
545 default:
546 return -1;
547 }
548
549 switch (protocol) {
550 case IPPROTO_UDP:
junyulaic4e591a2018-11-26 22:36:10 +0900551 return ((struct udphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900552
553 case IPPROTO_TCP:
junyulaic4e591a2018-11-26 22:36:10 +0900554 return ((struct tcphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900555
556 case IPPROTO_FRAGMENT:
557 default:
558 return -1;
559 }
560}
561
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900562static tun_data makeTunData() {
563 // Create some fake but realistic-looking sockets so update_clat_ipv6_address doesn't balk.
564 return {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900565 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
Nick Desaulniers75f4dc62019-11-19 09:37:42 -0800566 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900567 .fd4 = socket(AF_UNIX, SOCK_DGRAM, 0),
568 };
569}
570
571void freeTunData(tun_data *tunnel) {
572 close(tunnel->write_fd6);
573 close(tunnel->read_fd6);
574 close(tunnel->fd4);
575}
576
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900577struct clat_config Global_Clatd_Config;
578
579class ClatdTest : public ::testing::Test {
580 protected:
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900581 static TunInterface sTun;
582
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900583 virtual void SetUp() {
584 inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
585 inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900586 memset(&Global_Clatd_Config.ipv6_local_subnet, 0, sizeof(in6_addr));
Maciej Żenczykowskiba667df2020-06-02 01:41:54 -0700587 Global_Clatd_Config.native_ipv6_interface = const_cast<char *>(sTun.name().c_str());
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900588 }
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900589
590 // Static because setting up the tun interface takes about 40ms.
591 static void SetUpTestCase() { ASSERT_EQ(0, sTun.init()); }
592
593 // Closing the socket removes the interface and IP addresses.
594 static void TearDownTestCase() { sTun.destroy(); }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900595};
596
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900597TunInterface ClatdTest::sTun;
598
Lorenzo Colitti98089522014-10-09 22:29:45 +0900599void expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
600 if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
601 char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
602 inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
603 inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
604 FAIL()
605 << "Unexpected IPv6 address:: "
606 << "\n Expected: " << expected_str
607 << "\n Actual: " << actual_str
608 << "\n";
609 }
610}
611
612TEST_F(ClatdTest, TestIPv6PrefixEqual) {
613 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
614 &Global_Clatd_Config.plat_subnet));
615 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
616 &Global_Clatd_Config.ipv6_local_subnet));
617
618 struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
619 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
620 EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
621
622 subnet2.s6_addr[6] = 0xff;
623 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
624 EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
625}
626
Maciej Żenczykowskib00113f2020-01-18 23:56:14 -0800627TEST_F(ClatdTest, DetectMtu) {
628 // ::1 with bottom 32 bits set to 1 is still ::1 which routes via lo with mtu of 64KiB
629 ASSERT_EQ(detect_mtu(&in6addr_loopback, htonl(1), 0 /*MARK_UNSET*/), 65536);
630}
631
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900632TEST_F(ClatdTest, ConfigureTunIpManual) {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900633 // Create an interface for configure_tun_ip to configure and bring up.
634 TunInterface v4Iface;
635 ASSERT_EQ(0, v4Iface.init());
636 struct tun_data tunnel = makeTunData();
637 strlcpy(tunnel.device4, v4Iface.name().c_str(), sizeof(tunnel.device4));
638
Maciej Żenczykowskib00113f2020-01-18 23:56:14 -0800639 configure_tun_ip(&tunnel, "192.0.2.1" /* v4_addr */, 1472);
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900640 EXPECT_EQ(inet_addr("192.0.2.1"), Global_Clatd_Config.ipv4_local_subnet.s_addr);
641
642 union anyip *ip = getinterface_ip(v4Iface.name().c_str(), AF_INET);
643 ASSERT_NE(nullptr, ip);
644 EXPECT_EQ(inet_addr("192.0.2.1"), ip->ip4.s_addr);
645 free(ip);
646
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900647 v4Iface.destroy();
648}
649
Lorenzo Colitti98089522014-10-09 22:29:45 +0900650TEST_F(ClatdTest, DataSanitycheck) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900651 // Sanity checks the data.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800652 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900653 ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
654
Brian Carlstromfcac4102014-02-24 20:03:01 -0800655 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900656 ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
657
Brian Carlstromfcac4102014-02-24 20:03:01 -0800658 uint8_t udp_header[] = { UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900659 ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
660
661 // Sanity checks check_packet.
662 struct udphdr *udp;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800663 uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900664 udp = (struct udphdr *)(v4_udp_packet + sizeof(struct iphdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900665 fix_udp_checksum(v4_udp_packet);
666 ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
667 check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
668
Brian Carlstromfcac4102014-02-24 20:03:01 -0800669 uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900670 udp = (struct udphdr *)(v6_udp_packet + sizeof(struct ip6_hdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900671 fix_udp_checksum(v6_udp_packet);
672 ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
673 check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
674
Brian Carlstromfcac4102014-02-24 20:03:01 -0800675 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900676 check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
677
Brian Carlstromfcac4102014-02-24 20:03:01 -0800678 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900679 check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
680
681 // Sanity checks reassemble_packet.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800682 uint8_t reassembled[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900683 size_t total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900684 reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), reassembled,
685 &total_length, "Reassembly sanity check");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900686 check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
687 ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
junyulaic4e591a2018-11-26 22:36:10 +0900688 ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *)reassembled))
689 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900690 check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
691
692 total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900693 reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments), reassembled,
694 &total_length, "IPv6 reassembly sanity check");
695 ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *)reassembled, total_length))
696 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900697 check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
698}
699
700TEST_F(ClatdTest, PseudoChecksum) {
701 uint32_t pseudo_checksum;
702
junyulaic4e591a2018-11-26 22:36:10 +0900703 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800704 uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900705 pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *)v4_header, UDP_LEN);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900706 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
707 ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900708 << "ipv4_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900709
junyulaic4e591a2018-11-26 22:36:10 +0900710 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800711 uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900712 pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *)v6_header, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900713 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
714 ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900715 << "ipv6_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900716}
717
718TEST_F(ClatdTest, TransportChecksum) {
junyulaic4e591a2018-11-26 22:36:10 +0900719 uint8_t udphdr[] = { UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800720 uint8_t payload[] = { PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900721 EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
junyulaic4e591a2018-11-26 22:36:10 +0900722 << "UDP partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900723 EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
junyulaic4e591a2018-11-26 22:36:10 +0900724 << "Payload partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900725
junyulaic4e591a2018-11-26 22:36:10 +0900726 uint8_t ip[] = { IPV4_UDP_HEADER };
727 uint8_t ip6[] = { IPV6_UDP_HEADER };
728 uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *)ip, UDP_LEN);
729 uint32_t ipv6_pseudo_sum =
730 ipv6_pseudo_header_checksum((struct ip6_hdr *)ip6, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900731
Maciej Żenczykowskif037e772019-11-10 23:02:13 -0800732 EXPECT_NE(0, ipv4_pseudo_sum);
733 EXPECT_NE(0, ipv6_pseudo_sum);
734 EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum % 0xFFFF) << "IPv4 pseudo-checksum sanity check\n";
735 EXPECT_EQ(0x644dU, ipv6_pseudo_sum % 0xFFFF) << "IPv6 pseudo-checksum sanity check\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900736 EXPECT_EQ(
737 kUdpV4Checksum,
738 ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
739 << "Unexpected UDP/IPv4 checksum\n";
740 EXPECT_EQ(
741 kUdpV6Checksum,
742 ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
743 << "Unexpected UDP/IPv6 checksum\n";
744
745 EXPECT_EQ(kUdpV6Checksum,
746 ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
747 << "Adjust IPv4/UDP checksum to IPv6\n";
748 EXPECT_EQ(kUdpV4Checksum,
749 ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
750 << "Adjust IPv6/UDP checksum to IPv4\n";
751}
752
753TEST_F(ClatdTest, AdjustChecksum) {
754 struct checksum_data {
755 uint16_t checksum;
756 uint32_t old_hdr_sum;
757 uint32_t new_hdr_sum;
758 uint16_t result;
759 } DATA[] = {
760 { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
761 { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
762 { 0xdd2f, 0x5555, 0x3285, 0x0000 },
763 { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
764 { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
765 };
Chih-Hung Hsieh05ff5082014-08-26 10:46:26 -0700766 unsigned i = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900767
768 for (i = 0; i < ARRAYSIZE(DATA); i++) {
769 struct checksum_data *data = DATA + i;
770 uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
771 EXPECT_EQ(result, data->result)
772 << "Incorrect checksum" << std::showbase << std::hex
773 << "\n Expected: " << data->result
774 << "\n Actual: " << result
775 << "\n checksum=" << data->checksum
776 << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
777 }
778}
779
780TEST_F(ClatdTest, Translate) {
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900781 // This test uses hardcoded packets so the clatd address must be fixed.
782 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
783
Brian Carlstromfcac4102014-02-24 20:03:01 -0800784 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
785 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900786 fix_udp_checksum(udp_ipv4);
787 fix_udp_checksum(udp_ipv6);
788 check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
789 "UDP/IPv4 -> UDP/IPv6 translation");
790 check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
791 "UDP/IPv6 -> UDP/IPv4 translation");
792
Brian Carlstromfcac4102014-02-24 20:03:01 -0800793 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
794 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900795 check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
796 "ICMP->ICMPv6 translation");
797 check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
798 "ICMPv6->ICMP translation");
799}
800
801TEST_F(ClatdTest, Fragmentation) {
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900802 // This test uses hardcoded packets so the clatd address must be fixed.
803 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
804
junyulaic4e591a2018-11-26 22:36:10 +0900805 check_fragment_translation(kIPv4Fragments, kIPv4FragLengths, kIPv6Fragments, kIPv6FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900806 ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
807
junyulaic4e591a2018-11-26 22:36:10 +0900808 check_fragment_translation(kIPv6Fragments, kIPv6FragLengths, kIPv4Fragments, kIPv4FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900809 ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
810}
Lorenzo Colitti98089522014-10-09 22:29:45 +0900811
Lorenzo Colittibaa3c6a2020-06-02 01:55:12 +0900812// picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix
813void gen_random_iid(struct in6_addr *myaddr, struct in_addr *ipv4_local_subnet,
814 struct in6_addr *plat_subnet) {
815 // Fill last 8 bytes of IPv6 address with random bits.
816 arc4random_buf(&myaddr->s6_addr[8], 8);
817
818 // Make the IID checksum-neutral. That is, make it so that:
819 // checksum(Local IPv4 | Remote IPv4) = checksum(Local IPv6 | Remote IPv6)
820 // in other words (because remote IPv6 = NAT64 prefix | Remote IPv4):
821 // checksum(Local IPv4) = checksum(Local IPv6 | NAT64 prefix)
822 // Do this by adjusting the two bytes in the middle of the IID.
823
824 uint16_t middlebytes = (myaddr->s6_addr[11] << 8) + myaddr->s6_addr[12];
825
826 uint32_t c1 = ip_checksum_add(0, ipv4_local_subnet, sizeof(*ipv4_local_subnet));
827 uint32_t c2 = ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
828 ip_checksum_add(0, myaddr, sizeof(*myaddr));
829
830 uint16_t delta = ip_checksum_adjust(middlebytes, c1, c2);
831 myaddr->s6_addr[11] = delta >> 8;
832 myaddr->s6_addr[12] = delta & 0xff;
833}
834
Lorenzo Colitti98089522014-10-09 22:29:45 +0900835void check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
836 size_t expected_len, const char *msg) {
837 uint8_t translated[MAXMTU];
838 size_t translated_len = sizeof(translated);
839 do_translate_packet(original, original_len, translated, &translated_len, msg);
840 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
841 // do_translate_packet already checks packets for validity and verifies the checksum.
junyulaic4e591a2018-11-26 22:36:10 +0900842 int original_check = get_transport_checksum(original);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900843 int translated_check = get_transport_checksum(translated);
844 ASSERT_NE(-1, original_check);
845 ASSERT_NE(-1, translated_check);
846 ASSERT_EQ(original_check, translated_check)
junyulaic4e591a2018-11-26 22:36:10 +0900847 << "Not checksum neutral: original and translated checksums differ\n";
Lorenzo Colitti98089522014-10-09 22:29:45 +0900848}
849
850TEST_F(ClatdTest, TranslateChecksumNeutral) {
851 // Generate a random clat IPv6 address and check that translation is checksum-neutral.
Lorenzo Colitti98089522014-10-09 22:29:45 +0900852 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
853 &Global_Clatd_Config.ipv6_local_subnet));
Lorenzo Colittibaa3c6a2020-06-02 01:55:12 +0900854
855 gen_random_iid(&Global_Clatd_Config.ipv6_local_subnet, &Global_Clatd_Config.ipv4_local_subnet,
856 &Global_Clatd_Config.plat_subnet);
857
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900858 ASSERT_NE(htonl((uint32_t)0x00000464), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
junyulaic4e591a2018-11-26 22:36:10 +0900859 ASSERT_NE((uint32_t)0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900860
861 // Check that translating UDP packets is checksum-neutral. First, IPv4.
862 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
863 fix_udp_checksum(udp_ipv4);
864 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
865 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
866
867 // Now try IPv6.
868 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
869 // The test packet uses the static IID, not the random IID. Fix up the source address.
junyulaic4e591a2018-11-26 22:36:10 +0900870 struct ip6_hdr *ip6 = (struct ip6_hdr *)udp_ipv6;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900871 memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
872 fix_udp_checksum(udp_ipv6);
873 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
874 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
875}
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900876
877TEST_F(ClatdTest, GetInterfaceIp) {
878 union anyip *ip = getinterface_ip(sTun.name().c_str(), AF_INET6);
879 ASSERT_NE(nullptr, ip);
880 in6_addr expected = sTun.srcAddr();
881 in6_addr actual = ip->ip6;
882 expect_ipv6_addr_equal(&expected, &actual);
883}
884
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900885void expectSocketBound(int ifindex, int sock) {
886 // Check that the packet socket is bound to the interface. We can't check the socket filter
887 // because there is no way to fetch it from the kernel.
888 sockaddr_ll sll;
889 socklen_t len = sizeof(sll);
890 ASSERT_EQ(0, getsockname(sock, reinterpret_cast<sockaddr *>(&sll), &len));
891 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
892 EXPECT_EQ(ifindex, sll.sll_ifindex);
893}
894
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900895TEST_F(ClatdTest, ConfigureIpv6Address) {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900896 struct tun_data tunnel = makeTunData();
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900897
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900898 ASSERT_TRUE(IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_local_subnet));
899
900 const char *addrStr = "2001:db8::f00";
901 in6_addr addr;
902 ASSERT_EQ(1, inet_pton(AF_INET6, addrStr, &addr));
903 ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, sTun.name().c_str(), addrStr));
904
905 EXPECT_EQ(htonl(0x20010db8), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[0]);
906 EXPECT_EQ(htonl(0x00000000), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[1]);
907 EXPECT_EQ(htonl(0x00000000), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[2]);
908 EXPECT_EQ(htonl(0x00000f00), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
909
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900910 // Check that the packet socket is bound to the interface. We can't check the socket filter
911 // because there is no way to fetch it from the kernel.
912 sockaddr_ll sll;
913 socklen_t len = sizeof(sll);
914 ASSERT_EQ(0, getsockname(tunnel.read_fd6, reinterpret_cast<sockaddr *>(&sll), &len));
915 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
916 EXPECT_EQ(sll.sll_ifindex, sTun.ifindex());
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900917
918 expectSocketBound(sTun.ifindex(), tunnel.read_fd6);
919
920 freeTunData(&tunnel);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900921}
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900922
923TEST_F(ClatdTest, Ipv6AddressChanged) {
924 // Configure the clat IPv6 address.
925 struct tun_data tunnel = {
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900926 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
Nick Desaulniers75f4dc62019-11-19 09:37:42 -0800927 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900928 };
929 const char *ifname = sTun.name().c_str();
Lorenzo Colittibaa3c6a2020-06-02 01:55:12 +0900930
931 in6_addr myaddr = sTun.srcAddr();
932 gen_random_iid(&myaddr, &Global_Clatd_Config.ipv4_local_subnet, &Global_Clatd_Config.plat_subnet);
933 char addrstr[INET6_ADDRSTRLEN];
934 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &myaddr, addrstr, sizeof(addrstr)));
935
936 ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, ifname, addrstr));
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900937 EXPECT_EQ(0, ipv6_address_changed(ifname));
938 EXPECT_EQ(0, ipv6_address_changed(ifname));
939
940 // Change the IP address on the tun interface to a new prefix.
941 char srcaddr[INET6_ADDRSTRLEN];
942 char dstaddr[INET6_ADDRSTRLEN];
943 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.srcAddr(), srcaddr, sizeof(srcaddr)));
944 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.dstAddr(), dstaddr, sizeof(dstaddr)));
945 EXPECT_EQ(0, ifc_del_address(ifname, srcaddr, 64));
946 EXPECT_EQ(0, ifc_del_address(ifname, dstaddr, 64));
947
948 // Check that we can tell that the address has changed.
949 EXPECT_EQ(0, ifc_add_address(ifname, "2001:db8::1:2", 64));
950 EXPECT_EQ(1, ipv6_address_changed(ifname));
951 EXPECT_EQ(1, ipv6_address_changed(ifname));
952
953 // Restore the tun interface configuration.
954 sTun.destroy();
955 ASSERT_EQ(0, sTun.init());
956}