blob: bd2fb9ff5046ca01fa1dbb5d0d8eb6537bd04995 [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>
27
Lorenzo Colitti66deecd2019-01-04 12:27:27 +090028#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
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600464 translate_packet(write_fd, (version == 4), original, original_len, TP_CSUM_NONE);
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
Brian Carlstromfcac4102014-02-24 20:03:01 -0800492void check_translated_packet(const uint8_t *original, size_t original_len,
493 const uint8_t *expected, size_t expected_len, const char *msg) {
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600494 uint8_t *translated = new uint8_t[MAXMRU];
495 ASSERT_NE(translated, nullptr) << msg << ": Unable to allocate memory\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900496 size_t translated_len = sizeof(translated);
497 do_translate_packet(original, original_len, translated, &translated_len, msg);
498 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
499 check_data_matches(expected, translated, translated_len, msg);
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600500 delete [] translated;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900501}
502
Brian Carlstromfcac4102014-02-24 20:03:01 -0800503void check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
504 const uint8_t *expected[], const size_t expected_lengths[],
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900505 int numfragments, const char *msg) {
506 for (int i = 0; i < numfragments; i++) {
507 // Check that each of the fragments translates as expected.
508 char frag_msg[512];
509 snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
junyulaic4e591a2018-11-26 22:36:10 +0900510 check_translated_packet(original[i], original_lengths[i], expected[i], expected_lengths[i],
511 frag_msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900512 }
513
514 // Sanity check that reassembling the original and translated fragments produces valid packets.
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600515 uint8_t *reassembled = new uint8_t[MAXMRU];
516 ASSERT_NE(reassembled, nullptr) << msg << ": Unable to allocate memory\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900517 size_t reassembled_len = sizeof(reassembled);
518 reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
519 check_packet(reassembled, reassembled_len, msg);
520
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600521 uint8_t *translated = new uint8_t[MAXMRU];
522 ASSERT_NE(translated, nullptr) << msg << ": Unable to allocate memory\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900523 size_t translated_len = sizeof(translated);
524 do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
525 check_packet(translated, translated_len, msg);
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600526
527 delete [] translated;
528 delete [] reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900529}
530
Lorenzo Colitti98089522014-10-09 22:29:45 +0900531int get_transport_checksum(const uint8_t *packet) {
532 struct iphdr *ip;
533 struct ip6_hdr *ip6;
534 uint8_t protocol;
535 const void *payload;
536
537 int version = ip_version(packet);
538 switch (version) {
539 case 4:
junyulaic4e591a2018-11-26 22:36:10 +0900540 ip = (struct iphdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900541 if (is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900542 return -1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900543 }
544 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900545 payload = ip + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900546 break;
547 case 6:
junyulaic4e591a2018-11-26 22:36:10 +0900548 ip6 = (struct ip6_hdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900549 protocol = ip6->ip6_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900550 payload = ip6 + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900551 break;
552 default:
553 return -1;
554 }
555
556 switch (protocol) {
557 case IPPROTO_UDP:
junyulaic4e591a2018-11-26 22:36:10 +0900558 return ((struct udphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900559
560 case IPPROTO_TCP:
junyulaic4e591a2018-11-26 22:36:10 +0900561 return ((struct tcphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900562
563 case IPPROTO_FRAGMENT:
564 default:
565 return -1;
566 }
567}
568
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900569static tun_data makeTunData() {
570 // Create some fake but realistic-looking sockets so update_clat_ipv6_address doesn't balk.
571 return {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900572 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
Nick Desaulniers75f4dc62019-11-19 09:37:42 -0800573 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900574 .fd4 = socket(AF_UNIX, SOCK_DGRAM, 0),
575 };
576}
577
578void freeTunData(tun_data *tunnel) {
579 close(tunnel->write_fd6);
580 close(tunnel->read_fd6);
581 close(tunnel->fd4);
582}
583
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900584struct clat_config Global_Clatd_Config;
585
586class ClatdTest : public ::testing::Test {
587 protected:
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900588 static TunInterface sTun;
589
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900590 virtual void SetUp() {
591 inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
592 inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900593 memset(&Global_Clatd_Config.ipv6_local_subnet, 0, sizeof(in6_addr));
Maciej Żenczykowski8452f3f2020-06-03 02:31:51 +0000594 Global_Clatd_Config.native_ipv6_interface = const_cast<char *>(sTun.name().c_str());
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900595 }
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900596
597 // Static because setting up the tun interface takes about 40ms.
598 static void SetUpTestCase() { ASSERT_EQ(0, sTun.init()); }
599
600 // Closing the socket removes the interface and IP addresses.
601 static void TearDownTestCase() { sTun.destroy(); }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900602};
603
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900604TunInterface ClatdTest::sTun;
605
Lorenzo Colitti98089522014-10-09 22:29:45 +0900606void expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
607 if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
608 char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
609 inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
610 inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
611 FAIL()
612 << "Unexpected IPv6 address:: "
613 << "\n Expected: " << expected_str
614 << "\n Actual: " << actual_str
615 << "\n";
616 }
617}
618
619TEST_F(ClatdTest, TestIPv6PrefixEqual) {
620 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
621 &Global_Clatd_Config.plat_subnet));
622 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
623 &Global_Clatd_Config.ipv6_local_subnet));
624
625 struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
626 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
627 EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
628
629 subnet2.s6_addr[6] = 0xff;
630 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
631 EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
632}
633
Maciej Żenczykowskib00113f2020-01-18 23:56:14 -0800634TEST_F(ClatdTest, DetectMtu) {
635 // ::1 with bottom 32 bits set to 1 is still ::1 which routes via lo with mtu of 64KiB
636 ASSERT_EQ(detect_mtu(&in6addr_loopback, htonl(1), 0 /*MARK_UNSET*/), 65536);
637}
638
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900639TEST_F(ClatdTest, ConfigureTunIpManual) {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900640 // Create an interface for configure_tun_ip to configure and bring up.
641 TunInterface v4Iface;
642 ASSERT_EQ(0, v4Iface.init());
643 struct tun_data tunnel = makeTunData();
644 strlcpy(tunnel.device4, v4Iface.name().c_str(), sizeof(tunnel.device4));
645
Maciej Żenczykowskib00113f2020-01-18 23:56:14 -0800646 configure_tun_ip(&tunnel, "192.0.2.1" /* v4_addr */, 1472);
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900647 EXPECT_EQ(inet_addr("192.0.2.1"), Global_Clatd_Config.ipv4_local_subnet.s_addr);
648
649 union anyip *ip = getinterface_ip(v4Iface.name().c_str(), AF_INET);
650 ASSERT_NE(nullptr, ip);
651 EXPECT_EQ(inet_addr("192.0.2.1"), ip->ip4.s_addr);
652 free(ip);
653
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900654 v4Iface.destroy();
655}
656
Lorenzo Colitti98089522014-10-09 22:29:45 +0900657TEST_F(ClatdTest, DataSanitycheck) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900658 // Sanity checks the data.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800659 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900660 ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
661
Brian Carlstromfcac4102014-02-24 20:03:01 -0800662 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900663 ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
664
Brian Carlstromfcac4102014-02-24 20:03:01 -0800665 uint8_t udp_header[] = { UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900666 ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
667
668 // Sanity checks check_packet.
669 struct udphdr *udp;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800670 uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900671 udp = (struct udphdr *)(v4_udp_packet + sizeof(struct iphdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900672 fix_udp_checksum(v4_udp_packet);
673 ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
674 check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
675
Brian Carlstromfcac4102014-02-24 20:03:01 -0800676 uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900677 udp = (struct udphdr *)(v6_udp_packet + sizeof(struct ip6_hdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900678 fix_udp_checksum(v6_udp_packet);
679 ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
680 check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
681
Brian Carlstromfcac4102014-02-24 20:03:01 -0800682 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900683 check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
684
Brian Carlstromfcac4102014-02-24 20:03:01 -0800685 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900686 check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
687
688 // Sanity checks reassemble_packet.
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600689 uint8_t *reassembled = new uint8_t[MAXMRU];
690 ASSERT_NE(reassembled, nullptr) << ": Unable to allocate memory\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900691 size_t total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900692 reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), reassembled,
693 &total_length, "Reassembly sanity check");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900694 check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
695 ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
junyulaic4e591a2018-11-26 22:36:10 +0900696 ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *)reassembled))
697 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900698 check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
699
700 total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900701 reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments), reassembled,
702 &total_length, "IPv6 reassembly sanity check");
703 ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *)reassembled, total_length))
704 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900705 check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600706 delete [] reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900707}
708
709TEST_F(ClatdTest, PseudoChecksum) {
710 uint32_t pseudo_checksum;
711
junyulaic4e591a2018-11-26 22:36:10 +0900712 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800713 uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900714 pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *)v4_header, UDP_LEN);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900715 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
716 ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900717 << "ipv4_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900718
junyulaic4e591a2018-11-26 22:36:10 +0900719 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800720 uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900721 pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *)v6_header, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900722 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
723 ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900724 << "ipv6_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900725}
726
727TEST_F(ClatdTest, TransportChecksum) {
junyulaic4e591a2018-11-26 22:36:10 +0900728 uint8_t udphdr[] = { UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800729 uint8_t payload[] = { PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900730 EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
junyulaic4e591a2018-11-26 22:36:10 +0900731 << "UDP partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900732 EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
junyulaic4e591a2018-11-26 22:36:10 +0900733 << "Payload partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900734
junyulaic4e591a2018-11-26 22:36:10 +0900735 uint8_t ip[] = { IPV4_UDP_HEADER };
736 uint8_t ip6[] = { IPV6_UDP_HEADER };
737 uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *)ip, UDP_LEN);
738 uint32_t ipv6_pseudo_sum =
739 ipv6_pseudo_header_checksum((struct ip6_hdr *)ip6, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900740
Maciej Żenczykowskif037e772019-11-10 23:02:13 -0800741 EXPECT_NE(0, ipv4_pseudo_sum);
742 EXPECT_NE(0, ipv6_pseudo_sum);
743 EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum % 0xFFFF) << "IPv4 pseudo-checksum sanity check\n";
744 EXPECT_EQ(0x644dU, ipv6_pseudo_sum % 0xFFFF) << "IPv6 pseudo-checksum sanity check\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900745 EXPECT_EQ(
746 kUdpV4Checksum,
747 ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
748 << "Unexpected UDP/IPv4 checksum\n";
749 EXPECT_EQ(
750 kUdpV6Checksum,
751 ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
752 << "Unexpected UDP/IPv6 checksum\n";
753
754 EXPECT_EQ(kUdpV6Checksum,
755 ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
756 << "Adjust IPv4/UDP checksum to IPv6\n";
757 EXPECT_EQ(kUdpV4Checksum,
758 ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
759 << "Adjust IPv6/UDP checksum to IPv4\n";
760}
761
762TEST_F(ClatdTest, AdjustChecksum) {
763 struct checksum_data {
764 uint16_t checksum;
765 uint32_t old_hdr_sum;
766 uint32_t new_hdr_sum;
767 uint16_t result;
768 } DATA[] = {
769 { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
770 { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
771 { 0xdd2f, 0x5555, 0x3285, 0x0000 },
772 { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
773 { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
774 };
Chih-Hung Hsieh05ff5082014-08-26 10:46:26 -0700775 unsigned i = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900776
777 for (i = 0; i < ARRAYSIZE(DATA); i++) {
778 struct checksum_data *data = DATA + i;
779 uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
780 EXPECT_EQ(result, data->result)
781 << "Incorrect checksum" << std::showbase << std::hex
782 << "\n Expected: " << data->result
783 << "\n Actual: " << result
784 << "\n checksum=" << data->checksum
785 << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
786 }
787}
788
789TEST_F(ClatdTest, Translate) {
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900790 // This test uses hardcoded packets so the clatd address must be fixed.
791 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
792
Brian Carlstromfcac4102014-02-24 20:03:01 -0800793 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
794 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900795 fix_udp_checksum(udp_ipv4);
796 fix_udp_checksum(udp_ipv6);
797 check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
798 "UDP/IPv4 -> UDP/IPv6 translation");
799 check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
800 "UDP/IPv6 -> UDP/IPv4 translation");
801
Brian Carlstromfcac4102014-02-24 20:03:01 -0800802 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
803 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900804 check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
805 "ICMP->ICMPv6 translation");
806 check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
807 "ICMPv6->ICMP translation");
808}
809
810TEST_F(ClatdTest, Fragmentation) {
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900811 // This test uses hardcoded packets so the clatd address must be fixed.
812 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
813
junyulaic4e591a2018-11-26 22:36:10 +0900814 check_fragment_translation(kIPv4Fragments, kIPv4FragLengths, kIPv6Fragments, kIPv6FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900815 ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
816
junyulaic4e591a2018-11-26 22:36:10 +0900817 check_fragment_translation(kIPv6Fragments, kIPv6FragLengths, kIPv4Fragments, kIPv4FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900818 ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
819}
Lorenzo Colitti98089522014-10-09 22:29:45 +0900820
Maciej Żenczykowskif13d5692020-06-02 06:22:22 +0000821// picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix
822void gen_random_iid(struct in6_addr *myaddr, struct in_addr *ipv4_local_subnet,
823 struct in6_addr *plat_subnet) {
824 // Fill last 8 bytes of IPv6 address with random bits.
825 arc4random_buf(&myaddr->s6_addr[8], 8);
826
827 // Make the IID checksum-neutral. That is, make it so that:
828 // checksum(Local IPv4 | Remote IPv4) = checksum(Local IPv6 | Remote IPv6)
829 // in other words (because remote IPv6 = NAT64 prefix | Remote IPv4):
830 // checksum(Local IPv4) = checksum(Local IPv6 | NAT64 prefix)
831 // Do this by adjusting the two bytes in the middle of the IID.
832
833 uint16_t middlebytes = (myaddr->s6_addr[11] << 8) + myaddr->s6_addr[12];
834
835 uint32_t c1 = ip_checksum_add(0, ipv4_local_subnet, sizeof(*ipv4_local_subnet));
836 uint32_t c2 = ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
837 ip_checksum_add(0, myaddr, sizeof(*myaddr));
838
839 uint16_t delta = ip_checksum_adjust(middlebytes, c1, c2);
840 myaddr->s6_addr[11] = delta >> 8;
841 myaddr->s6_addr[12] = delta & 0xff;
842}
843
Lorenzo Colitti98089522014-10-09 22:29:45 +0900844void check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
845 size_t expected_len, const char *msg) {
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600846 uint8_t *translated = new uint8_t[MAXMRU];
847 ASSERT_NE(translated, nullptr) << msg << ": Unable to allocate memory\n";
Lorenzo Colitti98089522014-10-09 22:29:45 +0900848 size_t translated_len = sizeof(translated);
849 do_translate_packet(original, original_len, translated, &translated_len, msg);
850 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
851 // do_translate_packet already checks packets for validity and verifies the checksum.
junyulaic4e591a2018-11-26 22:36:10 +0900852 int original_check = get_transport_checksum(original);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900853 int translated_check = get_transport_checksum(translated);
854 ASSERT_NE(-1, original_check);
855 ASSERT_NE(-1, translated_check);
856 ASSERT_EQ(original_check, translated_check)
junyulaic4e591a2018-11-26 22:36:10 +0900857 << "Not checksum neutral: original and translated checksums differ\n";
Subash Abhinov Kasiviswanathan5c5b5342015-10-26 18:45:04 -0600858 delete [] translated;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900859}
860
861TEST_F(ClatdTest, TranslateChecksumNeutral) {
862 // Generate a random clat IPv6 address and check that translation is checksum-neutral.
Lorenzo Colitti98089522014-10-09 22:29:45 +0900863 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
864 &Global_Clatd_Config.ipv6_local_subnet));
Maciej Żenczykowskif13d5692020-06-02 06:22:22 +0000865
866 gen_random_iid(&Global_Clatd_Config.ipv6_local_subnet, &Global_Clatd_Config.ipv4_local_subnet,
867 &Global_Clatd_Config.plat_subnet);
868
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900869 ASSERT_NE(htonl((uint32_t)0x00000464), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
junyulaic4e591a2018-11-26 22:36:10 +0900870 ASSERT_NE((uint32_t)0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900871
872 // Check that translating UDP packets is checksum-neutral. First, IPv4.
873 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
874 fix_udp_checksum(udp_ipv4);
875 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
876 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
877
878 // Now try IPv6.
879 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
880 // The test packet uses the static IID, not the random IID. Fix up the source address.
junyulaic4e591a2018-11-26 22:36:10 +0900881 struct ip6_hdr *ip6 = (struct ip6_hdr *)udp_ipv6;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900882 memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
883 fix_udp_checksum(udp_ipv6);
884 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
885 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
886}
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900887
888TEST_F(ClatdTest, GetInterfaceIp) {
889 union anyip *ip = getinterface_ip(sTun.name().c_str(), AF_INET6);
890 ASSERT_NE(nullptr, ip);
891 in6_addr expected = sTun.srcAddr();
892 in6_addr actual = ip->ip6;
893 expect_ipv6_addr_equal(&expected, &actual);
894}
895
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900896void expectSocketBound(int ifindex, int sock) {
897 // Check that the packet socket is bound to the interface. We can't check the socket filter
898 // because there is no way to fetch it from the kernel.
899 sockaddr_ll sll;
900 socklen_t len = sizeof(sll);
901 ASSERT_EQ(0, getsockname(sock, reinterpret_cast<sockaddr *>(&sll), &len));
902 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
903 EXPECT_EQ(ifindex, sll.sll_ifindex);
904}
905
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900906TEST_F(ClatdTest, ConfigureIpv6Address) {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900907 struct tun_data tunnel = makeTunData();
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900908
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900909 ASSERT_TRUE(IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_local_subnet));
910
911 const char *addrStr = "2001:db8::f00";
912 in6_addr addr;
913 ASSERT_EQ(1, inet_pton(AF_INET6, addrStr, &addr));
914 ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, sTun.name().c_str(), addrStr));
915
916 EXPECT_EQ(htonl(0x20010db8), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[0]);
917 EXPECT_EQ(htonl(0x00000000), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[1]);
918 EXPECT_EQ(htonl(0x00000000), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[2]);
919 EXPECT_EQ(htonl(0x00000f00), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
920
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900921 // Check that the packet socket is bound to the interface. We can't check the socket filter
922 // because there is no way to fetch it from the kernel.
923 sockaddr_ll sll;
924 socklen_t len = sizeof(sll);
925 ASSERT_EQ(0, getsockname(tunnel.read_fd6, reinterpret_cast<sockaddr *>(&sll), &len));
926 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
927 EXPECT_EQ(sll.sll_ifindex, sTun.ifindex());
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900928
929 expectSocketBound(sTun.ifindex(), tunnel.read_fd6);
930
931 freeTunData(&tunnel);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900932}
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900933
934TEST_F(ClatdTest, Ipv6AddressChanged) {
935 // Configure the clat IPv6 address.
936 struct tun_data tunnel = {
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900937 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
Nick Desaulniers75f4dc62019-11-19 09:37:42 -0800938 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900939 };
940 const char *ifname = sTun.name().c_str();
Maciej Żenczykowskif13d5692020-06-02 06:22:22 +0000941
942 in6_addr myaddr = sTun.srcAddr();
943 gen_random_iid(&myaddr, &Global_Clatd_Config.ipv4_local_subnet, &Global_Clatd_Config.plat_subnet);
944 char addrstr[INET6_ADDRSTRLEN];
945 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &myaddr, addrstr, sizeof(addrstr)));
946
947 ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, ifname, addrstr));
Lorenzo Colitti66deecd2019-01-04 12:27:27 +0900948 EXPECT_EQ(0, ipv6_address_changed(ifname));
949 EXPECT_EQ(0, ipv6_address_changed(ifname));
950
951 // Change the IP address on the tun interface to a new prefix.
952 char srcaddr[INET6_ADDRSTRLEN];
953 char dstaddr[INET6_ADDRSTRLEN];
954 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.srcAddr(), srcaddr, sizeof(srcaddr)));
955 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.dstAddr(), dstaddr, sizeof(dstaddr)));
956 EXPECT_EQ(0, ifc_del_address(ifname, srcaddr, 64));
957 EXPECT_EQ(0, ifc_del_address(ifname, dstaddr, 64));
958
959 // Check that we can tell that the address has changed.
960 EXPECT_EQ(0, ifc_add_address(ifname, "2001:db8::1:2", 64));
961 EXPECT_EQ(1, ipv6_address_changed(ifname));
962 EXPECT_EQ(1, ipv6_address_changed(ifname));
963
964 // Restore the tun interface configuration.
965 sTun.destroy();
966 ASSERT_EQ(0, sTun.init());
967}