blob: 4f998ea319eaa245f7f652614815e9f99e6392b2 [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 Colitti72f770c2019-01-04 15:00:28 +090027#include "tun_interface.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090028
29extern "C" {
30#include "checksum.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090031#include "clatd.h"
junyulaic4e591a2018-11-26 22:36:10 +090032#include "config.h"
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090033#include "getaddr.h"
junyulaic4e591a2018-11-26 22:36:10 +090034#include "translate.h"
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090035#include "tun.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090036}
37
38// For convenience.
39#define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0])
40
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090041using android::net::TunInterface;
42
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090043// Default translation parameters.
junyulaic4e591a2018-11-26 22:36:10 +090044static const char kIPv4LocalAddr[] = "192.0.0.4";
45static const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090046static const char kIPv6PlatSubnet[] = "64:ff9b::";
47
junyulaic4e591a2018-11-26 22:36:10 +090048// clang-format off
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090049// Test packet portions. Defined as macros because it's easy to concatenate them to make packets.
50#define IPV4_HEADER(p, c1, c2) \
51 0x45, 0x00, 0, 41, /* Version=4, IHL=5, ToS=0x80, len=41 */ \
52 0x00, 0x00, 0x40, 0x00, /* ID=0x0000, flags=IP_DF, offset=0 */ \
53 55, (p), (c1), (c2), /* TTL=55, protocol=p, checksum=c1,c2 */ \
54 192, 0, 0, 4, /* Src=192.0.0.4 */ \
55 8, 8, 8, 8, /* Dst=8.8.8.8 */
56#define IPV4_UDP_HEADER IPV4_HEADER(IPPROTO_UDP, 0x73, 0xb0)
57#define IPV4_ICMP_HEADER IPV4_HEADER(IPPROTO_ICMP, 0x73, 0xc0)
58
59#define IPV6_HEADER(p) \
60 0x60, 0x00, 0, 0, /* Version=6, tclass=0x00, flowlabel=0 */ \
61 0, 21, (p), 55, /* plen=11, nxthdr=p, hlim=55 */ \
62 0x20, 0x01, 0x0d, 0xb8, /* Src=2001:db8:0:b11::464 */ \
63 0x00, 0x00, 0x0b, 0x11, \
64 0x00, 0x00, 0x00, 0x00, \
65 0x00, 0x00, 0x04, 0x64, \
66 0x00, 0x64, 0xff, 0x9b, /* Dst=64:ff9b::8.8.8.8 */ \
67 0x00, 0x00, 0x00, 0x00, \
68 0x00, 0x00, 0x00, 0x00, \
69 0x08, 0x08, 0x08, 0x08,
70#define IPV6_UDP_HEADER IPV6_HEADER(IPPROTO_UDP)
71#define IPV6_ICMPV6_HEADER IPV6_HEADER(IPPROTO_ICMPV6)
72
73#define UDP_LEN 21
74#define UDP_HEADER \
75 0xc8, 0x8b, 0, 53, /* Port 51339->53 */ \
76 0x00, UDP_LEN, 0, 0, /* Length 21, checksum empty for now */
77
78#define PAYLOAD 'H', 'e', 'l', 'l', 'o', ' ', 0x4e, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0x00
79
80#define IPV4_PING \
81 0x08, 0x00, 0x88, 0xd0, /* Type 8, code 0, checksum 0x88d0 */ \
82 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
83
84#define IPV6_PING \
85 0x80, 0x00, 0xc3, 0x42, /* Type 128, code 0, checksum 0xc342 */ \
86 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
87
88// Macros to return pseudo-headers from packets.
89#define IPV4_PSEUDOHEADER(ip, tlen) \
90 ip[12], ip[13], ip[14], ip[15], /* Source address */ \
91 ip[16], ip[17], ip[18], ip[19], /* Destination address */ \
92 0, ip[9], /* 0, protocol */ \
93 ((tlen) >> 16) & 0xff, (tlen) & 0xff, /* Transport length */
94
95#define IPV6_PSEUDOHEADER(ip6, protocol, tlen) \
96 ip6[8], ip6[9], ip6[10], ip6[11], /* Source address */ \
97 ip6[12], ip6[13], ip6[14], ip6[15], \
98 ip6[16], ip6[17], ip6[18], ip6[19], \
99 ip6[20], ip6[21], ip6[22], ip6[23], \
100 ip6[24], ip6[25], ip6[26], ip6[27], /* Destination address */ \
101 ip6[28], ip6[29], ip6[30], ip6[31], \
102 ip6[32], ip6[33], ip6[34], ip6[35], \
103 ip6[36], ip6[37], ip6[38], ip6[39], \
104 ((tlen) >> 24) & 0xff, /* Transport length */ \
105 ((tlen) >> 16) & 0xff, \
106 ((tlen) >> 8) & 0xff, \
107 (tlen) & 0xff, \
108 0, 0, 0, (protocol),
109
110// A fragmented DNS request.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800111static const uint8_t kIPv4Frag1[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900112 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x00, 0x40, 0x11,
113 0x8c, 0x6d, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
114 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
115 0x01, 0x00, 0x00, 0x01, 0x00, 0x00
116};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800117static const uint8_t kIPv4Frag2[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900118 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x02, 0x40, 0x11,
119 0x8c, 0x6b, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
120 0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06,
121 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65
122};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800123static const uint8_t kIPv4Frag3[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900124 0x45, 0x00, 0x00, 0x1d, 0xfe, 0x47, 0x00, 0x04, 0x40, 0x11,
125 0xac, 0x70, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
126 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
127};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800128static const uint8_t *kIPv4Fragments[] = { kIPv4Frag1, kIPv4Frag2, kIPv4Frag3 };
129static const size_t kIPv4FragLengths[] = { sizeof(kIPv4Frag1), sizeof(kIPv4Frag2),
130 sizeof(kIPv4Frag3) };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900131
Brian Carlstromfcac4102014-02-24 20:03:01 -0800132static const uint8_t kIPv6Frag1[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900133 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
134 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
137 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x47, 0x14, 0x5d,
138 0x00, 0x35, 0x00, 0x29, 0xeb, 0x91, 0x50, 0x47, 0x01, 0x00,
139 0x00, 0x01, 0x00, 0x00
140};
141
Brian Carlstromfcac4102014-02-24 20:03:01 -0800142static const uint8_t kIPv6Frag2[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900143 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
144 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
147 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0xfe, 0x47, 0x00, 0x00,
148 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f,
149 0x6f, 0x67, 0x6c, 0x65
150};
151
Brian Carlstromfcac4102014-02-24 20:03:01 -0800152static const uint8_t kIPv6Frag3[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900153 0x60, 0x00, 0x00, 0x00, 0x00, 0x11, 0x2c, 0x40, 0x20, 0x01,
154 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
157 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0xfe, 0x47, 0x03, 0x63,
158 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
159};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800160static const uint8_t *kIPv6Fragments[] = { kIPv6Frag1, kIPv6Frag2, kIPv6Frag3 };
161static const size_t kIPv6FragLengths[] = { sizeof(kIPv6Frag1), sizeof(kIPv6Frag2),
162 sizeof(kIPv6Frag3) };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900163
Brian Carlstromfcac4102014-02-24 20:03:01 -0800164static const uint8_t kReassembledIPv4[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900165 0x45, 0x00, 0x00, 0x3d, 0xfe, 0x47, 0x00, 0x00, 0x40, 0x11,
166 0xac, 0x54, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
167 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
168 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67,
170 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
171 0x01
172};
junyulaic4e591a2018-11-26 22:36:10 +0900173// clang-format on
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900174
175// Expected checksums.
176static const uint32_t kUdpPartialChecksum = 0xd5c8;
177static const uint32_t kPayloadPartialChecksum = 0x31e9c;
178static const uint16_t kUdpV4Checksum = 0xd0c7;
179static const uint16_t kUdpV6Checksum = 0xa74a;
180
Brian Carlstromfcac4102014-02-24 20:03:01 -0800181uint8_t ip_version(const uint8_t *packet) {
182 uint8_t version = packet[0] >> 4;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900183 return version;
184}
185
186int is_ipv4_fragment(struct iphdr *ip) {
187 // A packet is a fragment if its fragment offset is nonzero or if the MF flag is set.
188 return ntohs(ip->frag_off) & (IP_OFFMASK | IP_MF);
189}
190
191int is_ipv6_fragment(struct ip6_hdr *ip6, size_t len) {
192 if (ip6->ip6_nxt != IPPROTO_FRAGMENT) {
193 return 0;
194 }
junyulaic4e591a2018-11-26 22:36:10 +0900195 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900196 return len >= sizeof(*ip6) + sizeof(*frag) &&
junyulaic4e591a2018-11-26 22:36:10 +0900197 (frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900198}
199
200int ipv4_fragment_offset(struct iphdr *ip) {
201 return ntohs(ip->frag_off) & IP_OFFMASK;
202}
203
204int ipv6_fragment_offset(struct ip6_frag *frag) {
205 return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3);
206}
207
Brian Carlstromfcac4102014-02-24 20:03:01 -0800208void check_packet(const uint8_t *packet, size_t len, const char *msg) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900209 void *payload;
junyulaic4e591a2018-11-26 22:36:10 +0900210 size_t payload_length = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900211 uint32_t pseudo_checksum = 0;
junyulaic4e591a2018-11-26 22:36:10 +0900212 uint8_t protocol = 0;
213 int version = ip_version(packet);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900214 switch (version) {
215 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900216 struct iphdr *ip = (struct iphdr *)packet;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900217 ASSERT_GE(len, sizeof(*ip)) << msg << ": IPv4 packet shorter than IPv4 header\n";
218 EXPECT_EQ(5, ip->ihl) << msg << ": Unsupported IP header length\n";
219 EXPECT_EQ(len, ntohs(ip->tot_len)) << msg << ": Incorrect IPv4 length\n";
220 EXPECT_EQ(0, ip_checksum(ip, sizeof(*ip))) << msg << ": Incorrect IP checksum\n";
221 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900222 payload = ip + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900223 if (!is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900224 payload_length = len - sizeof(*ip);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900225 pseudo_checksum = ipv4_pseudo_header_checksum(ip, payload_length);
226 }
227 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP)
junyulaic4e591a2018-11-26 22:36:10 +0900228 << msg << ": Unsupported IPv4 protocol " << protocol << "\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900229 break;
230 }
231 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900232 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900233 ASSERT_GE(len, sizeof(*ip6)) << msg << ": IPv6 packet shorter than IPv6 header\n";
234 EXPECT_EQ(len - sizeof(*ip6), htons(ip6->ip6_plen)) << msg << ": Incorrect IPv6 length\n";
235
236 if (ip6->ip6_nxt == IPPROTO_FRAGMENT) {
junyulaic4e591a2018-11-26 22:36:10 +0900237 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900238 ASSERT_GE(len, sizeof(*ip6) + sizeof(*frag))
junyulaic4e591a2018-11-26 22:36:10 +0900239 << msg << ": IPv6 fragment: short fragment header\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900240 protocol = frag->ip6f_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900241 payload = frag + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900242 // Even though the packet has a Fragment header, it might not be a fragment.
243 if (!is_ipv6_fragment(ip6, len)) {
244 payload_length = len - sizeof(*ip6) - sizeof(*frag);
245 }
246 } else {
247 // Since there are no extension headers except Fragment, this must be the payload.
junyulaic4e591a2018-11-26 22:36:10 +0900248 protocol = ip6->ip6_nxt;
249 payload = ip6 + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900250 payload_length = len - sizeof(*ip6);
251 }
252 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMPV6)
junyulaic4e591a2018-11-26 22:36:10 +0900253 << msg << ": Unsupported IPv6 next header " << protocol;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900254 if (payload_length) {
255 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, payload_length, protocol);
256 }
257 break;
258 }
259 default:
260 FAIL() << msg << ": Unsupported IP version " << version << "\n";
261 return;
262 }
263
264 // If we understand the payload, verify the checksum.
265 if (payload_length) {
266 uint16_t checksum;
junyulaic4e591a2018-11-26 22:36:10 +0900267 switch (protocol) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900268 case IPPROTO_UDP:
269 case IPPROTO_TCP:
270 case IPPROTO_ICMPV6:
271 checksum = ip_checksum_finish(ip_checksum_add(pseudo_checksum, payload, payload_length));
272 break;
273 case IPPROTO_ICMP:
274 checksum = ip_checksum(payload, payload_length);
275 break;
276 default:
277 checksum = 0; // Don't check.
278 break;
279 }
280 EXPECT_EQ(0, checksum) << msg << ": Incorrect transport checksum\n";
281 }
282
283 if (protocol == IPPROTO_UDP) {
junyulaic4e591a2018-11-26 22:36:10 +0900284 struct udphdr *udp = (struct udphdr *)payload;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900285 EXPECT_NE(0, udp->check) << msg << ": UDP checksum 0 should be 0xffff";
286 // If this is not a fragment, check the UDP length field.
287 if (payload_length) {
288 EXPECT_EQ(payload_length, ntohs(udp->len)) << msg << ": Incorrect UDP length\n";
289 }
290 }
291}
292
Brian Carlstromfcac4102014-02-24 20:03:01 -0800293void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int numpackets,
294 uint8_t *reassembled, size_t *reassembled_len, const char *msg) {
junyulaic4e591a2018-11-26 22:36:10 +0900295 struct iphdr *ip = NULL;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900296 struct ip6_hdr *ip6 = NULL;
junyulaic4e591a2018-11-26 22:36:10 +0900297 size_t total_length, pos = 0;
Ben Cheng932614e2014-04-02 17:00:26 -0700298 uint8_t protocol = 0;
junyulaic4e591a2018-11-26 22:36:10 +0900299 uint8_t version = ip_version(fragments[0]);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900300
301 for (int i = 0; i < numpackets; i++) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800302 const uint8_t *packet = fragments[i];
junyulaic4e591a2018-11-26 22:36:10 +0900303 int len = lengths[i];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900304 int headersize, payload_offset;
305
306 ASSERT_EQ(ip_version(packet), version) << msg << ": Inconsistent fragment versions\n";
307 check_packet(packet, len, "Fragment sanity check");
308
309 switch (version) {
310 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900311 struct iphdr *ip_orig = (struct iphdr *)packet;
312 headersize = sizeof(*ip_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900313 ASSERT_TRUE(is_ipv4_fragment(ip_orig))
junyulaic4e591a2018-11-26 22:36:10 +0900314 << msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n";
315 ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip) : 0))
316 << msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900317
junyulaic4e591a2018-11-26 22:36:10 +0900318 headersize = sizeof(*ip_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900319 payload_offset = headersize;
320 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900321 ip = (struct iphdr *)reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900322 }
323 break;
324 }
325 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900326 struct ip6_hdr *ip6_orig = (struct ip6_hdr *)packet;
327 struct ip6_frag *frag = (struct ip6_frag *)(ip6_orig + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900328 ASSERT_TRUE(is_ipv6_fragment(ip6_orig, len))
junyulaic4e591a2018-11-26 22:36:10 +0900329 << msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n";
330 ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6) : 0))
331 << msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900332
junyulaic4e591a2018-11-26 22:36:10 +0900333 headersize = sizeof(*ip6_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900334 payload_offset = sizeof(*ip6_orig) + sizeof(*frag);
335 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900336 ip6 = (struct ip6_hdr *)reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900337 protocol = frag->ip6f_nxt;
338 }
339 break;
340 }
341 default:
342 FAIL() << msg << ": Invalid IP version << " << version;
343 }
344
345 // If this is the first fragment, copy the header.
346 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900347 ASSERT_LT(headersize, (int)*reassembled_len) << msg << ": Reassembly buffer too small\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900348 memcpy(reassembled, packet, headersize);
349 total_length = headersize;
350 pos += headersize;
351 }
352
353 // Copy the payload.
354 int payload_length = len - payload_offset;
355 total_length += payload_length;
Ben Cheng932614e2014-04-02 17:00:26 -0700356 ASSERT_LT(total_length, *reassembled_len) << msg << ": Reassembly buffer too small\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900357 memcpy(reassembled + pos, packet + payload_offset, payload_length);
358 pos += payload_length;
359 }
360
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900361 // Fix up the reassembled headers to reflect fragmentation and length (and IPv4 checksum).
362 ASSERT_EQ(total_length, pos) << msg << ": Reassembled packet length incorrect\n";
363 if (ip) {
364 ip->frag_off &= ~htons(IP_MF);
365 ip->tot_len = htons(total_length);
junyulaic4e591a2018-11-26 22:36:10 +0900366 ip->check = 0;
367 ip->check = ip_checksum(ip, sizeof(*ip));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900368 ASSERT_FALSE(is_ipv4_fragment(ip)) << msg << ": reassembled IPv4 packet is a fragment!\n";
369 }
370 if (ip6) {
junyulaic4e591a2018-11-26 22:36:10 +0900371 ip6->ip6_nxt = protocol;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900372 ip6->ip6_plen = htons(total_length - sizeof(*ip6));
373 ASSERT_FALSE(is_ipv6_fragment(ip6, ip6->ip6_plen))
junyulaic4e591a2018-11-26 22:36:10 +0900374 << msg << ": reassembled IPv6 packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900375 }
376
377 *reassembled_len = total_length;
378}
379
Lorenzo Colitti98089522014-10-09 22:29:45 +0900380void check_data_matches(const void *expected, const void *actual, size_t len, const char *msg) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900381 if (memcmp(expected, actual, len)) {
382 // Hex dump, 20 bytes per line, one space between bytes (1 byte = 3 chars), indented by 4.
383 int hexdump_len = len * 3 + (len / 20 + 1) * 5;
384 char expected_hexdump[hexdump_len], actual_hexdump[hexdump_len];
385 unsigned pos = 0;
386 for (unsigned i = 0; i < len; i++) {
387 if (i % 20 == 0) {
George Burgess IV2dcca6f2016-02-24 15:55:54 -0800388 snprintf(expected_hexdump + pos, hexdump_len - pos, "\n ");
389 snprintf(actual_hexdump + pos, hexdump_len - pos, "\n ");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900390 pos += 4;
391 }
junyulaic4e591a2018-11-26 22:36:10 +0900392 snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)expected)[i]);
393 snprintf(actual_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)actual)[i]);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900394 pos += 3;
395 }
Lorenzo Colitti98089522014-10-09 22:29:45 +0900396 FAIL() << msg << ": Data doesn't match"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900397 << "\n Expected:" << (char *) expected_hexdump
398 << "\n Actual:" << (char *) actual_hexdump << "\n";
399 }
400}
401
junyulaic4e591a2018-11-26 22:36:10 +0900402void fix_udp_checksum(uint8_t *packet) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900403 uint32_t pseudo_checksum;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800404 uint8_t version = ip_version(packet);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900405 struct udphdr *udp;
406 switch (version) {
407 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900408 struct iphdr *ip = (struct iphdr *)packet;
409 udp = (struct udphdr *)(ip + 1);
410 pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900411 break;
412 }
413 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900414 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
415 udp = (struct udphdr *)(ip6 + 1);
416 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900417 break;
418 }
419 default:
420 FAIL() << "unsupported IP version" << version << "\n";
421 return;
junyulaic4e591a2018-11-26 22:36:10 +0900422 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900423
424 udp->check = 0;
425 udp->check = ip_checksum_finish(ip_checksum_add(pseudo_checksum, udp, ntohs(udp->len)));
426}
427
Lorenzo Colittice140882014-06-02 21:20:40 +0900428// Testing stub for send_rawv6. The real version uses sendmsg() with a
429// destination IPv6 address, and attempting to call that on our test socketpair
430// fd results in EINVAL.
junyulaic4e591a2018-11-26 22:36:10 +0900431extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) { writev(fd, out, iov_len); }
Lorenzo Colittice140882014-06-02 21:20:40 +0900432
Brian Carlstromfcac4102014-02-24 20:03:01 -0800433void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *out, size_t *outlen,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900434 const char *msg) {
435 int fds[2];
436 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, fds)) {
437 abort();
438 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900439
440 char foo[512];
441 snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg);
442 check_packet(original, original_len, foo);
443
Lorenzo Colittie24982e2014-06-02 15:49:36 +0900444 int read_fd, write_fd;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900445 uint16_t expected_proto;
446 int version = ip_version(original);
447 switch (version) {
448 case 4:
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900449 expected_proto = htons(ETH_P_IPV6);
junyulaic4e591a2018-11-26 22:36:10 +0900450 read_fd = fds[1];
451 write_fd = fds[0];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900452 break;
453 case 6:
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900454 expected_proto = htons(ETH_P_IP);
junyulaic4e591a2018-11-26 22:36:10 +0900455 read_fd = fds[0];
456 write_fd = fds[1];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900457 break;
458 default:
459 FAIL() << msg << ": Unsupported IP version " << version << "\n";
460 break;
461 }
462
Lorenzo Colittie24982e2014-06-02 15:49:36 +0900463 translate_packet(write_fd, (version == 4), original, original_len);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900464
Lorenzo Colitti98089522014-10-09 22:29:45 +0900465 snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
Lorenzo Colittice140882014-06-02 21:20:40 +0900466 if (version == 6) {
467 // Translating to IPv4. Expect a tun header.
468 struct tun_pi new_tun_header;
469 struct iovec iov[] = {
470 { &new_tun_header, sizeof(new_tun_header) },
junyulaic4e591a2018-11-26 22:36:10 +0900471 { out, *outlen },
Lorenzo Colittice140882014-06-02 21:20:40 +0900472 };
junyulaic4e591a2018-11-26 22:36:10 +0900473
Lorenzo Colittice140882014-06-02 21:20:40 +0900474 int len = readv(read_fd, iov, 2);
junyulaic4e591a2018-11-26 22:36:10 +0900475 if (len > (int)sizeof(new_tun_header)) {
476 ASSERT_LT((size_t)len, *outlen) << msg << ": Translated packet buffer too small\n";
Lorenzo Colittice140882014-06-02 21:20:40 +0900477 EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
478 *outlen = len - sizeof(new_tun_header);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900479 check_packet(out, *outlen, msg);
Lorenzo Colittice140882014-06-02 21:20:40 +0900480 } else {
Lorenzo Colitti98089522014-10-09 22:29:45 +0900481 FAIL() << msg << ": Packet was not translated: len=" << len;
Lorenzo Colittice140882014-06-02 21:20:40 +0900482 *outlen = 0;
483 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900484 } else {
Lorenzo Colittice140882014-06-02 21:20:40 +0900485 // Translating to IPv6. Expect raw packet.
486 *outlen = read(read_fd, out, *outlen);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900487 check_packet(out, *outlen, msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900488 }
489}
490
junyulaic4e591a2018-11-26 22:36:10 +0900491void check_translated_packet(const uint8_t *original, size_t original_len, const uint8_t *expected,
492 size_t expected_len, const char *msg) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800493 uint8_t translated[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900494 size_t translated_len = sizeof(translated);
495 do_translate_packet(original, original_len, translated, &translated_len, msg);
496 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
497 check_data_matches(expected, translated, translated_len, msg);
498}
499
Brian Carlstromfcac4102014-02-24 20:03:01 -0800500void check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
501 const uint8_t *expected[], const size_t expected_lengths[],
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900502 int numfragments, const char *msg) {
503 for (int i = 0; i < numfragments; i++) {
504 // Check that each of the fragments translates as expected.
505 char frag_msg[512];
506 snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
junyulaic4e591a2018-11-26 22:36:10 +0900507 check_translated_packet(original[i], original_lengths[i], expected[i], expected_lengths[i],
508 frag_msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900509 }
510
511 // Sanity check that reassembling the original and translated fragments produces valid packets.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800512 uint8_t reassembled[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900513 size_t reassembled_len = sizeof(reassembled);
514 reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
515 check_packet(reassembled, reassembled_len, msg);
516
Brian Carlstromfcac4102014-02-24 20:03:01 -0800517 uint8_t translated[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900518 size_t translated_len = sizeof(translated);
519 do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
520 check_packet(translated, translated_len, msg);
521}
522
Lorenzo Colitti98089522014-10-09 22:29:45 +0900523int get_transport_checksum(const uint8_t *packet) {
524 struct iphdr *ip;
525 struct ip6_hdr *ip6;
526 uint8_t protocol;
527 const void *payload;
528
529 int version = ip_version(packet);
530 switch (version) {
531 case 4:
junyulaic4e591a2018-11-26 22:36:10 +0900532 ip = (struct iphdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900533 if (is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900534 return -1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900535 }
536 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900537 payload = ip + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900538 break;
539 case 6:
junyulaic4e591a2018-11-26 22:36:10 +0900540 ip6 = (struct ip6_hdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900541 protocol = ip6->ip6_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900542 payload = ip6 + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900543 break;
544 default:
545 return -1;
546 }
547
548 switch (protocol) {
549 case IPPROTO_UDP:
junyulaic4e591a2018-11-26 22:36:10 +0900550 return ((struct udphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900551
552 case IPPROTO_TCP:
junyulaic4e591a2018-11-26 22:36:10 +0900553 return ((struct tcphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900554
555 case IPPROTO_FRAGMENT:
556 default:
557 return -1;
558 }
559}
560
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900561struct clat_config Global_Clatd_Config;
562
563class ClatdTest : public ::testing::Test {
564 protected:
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900565 static TunInterface sTun;
566
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900567 virtual void SetUp() {
568 inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
569 inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900570 memset(&Global_Clatd_Config.ipv6_local_subnet, 0, sizeof(in6_addr));
junyulaic4e591a2018-11-26 22:36:10 +0900571 Global_Clatd_Config.ipv6_host_id = in6addr_any;
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800572 Global_Clatd_Config.use_dynamic_iid = 1;
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900573 Global_Clatd_Config.default_pdp_interface = const_cast<char *>(sTun.name().c_str());
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900574 }
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900575
576 // Static because setting up the tun interface takes about 40ms.
577 static void SetUpTestCase() { ASSERT_EQ(0, sTun.init()); }
578
579 // Closing the socket removes the interface and IP addresses.
580 static void TearDownTestCase() { sTun.destroy(); }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900581};
582
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900583TunInterface ClatdTest::sTun;
584
Lorenzo Colitti98089522014-10-09 22:29:45 +0900585void expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
586 if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
587 char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
588 inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
589 inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
590 FAIL()
591 << "Unexpected IPv6 address:: "
592 << "\n Expected: " << expected_str
593 << "\n Actual: " << actual_str
594 << "\n";
595 }
596}
597
598TEST_F(ClatdTest, TestIPv6PrefixEqual) {
599 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
600 &Global_Clatd_Config.plat_subnet));
601 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
602 &Global_Clatd_Config.ipv6_local_subnet));
603
604 struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
605 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
606 EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
607
608 subnet2.s6_addr[6] = 0xff;
609 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
610 EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
611}
612
613int count_onebits(const void *data, size_t size) {
614 int onebits = 0;
615 for (size_t pos = 0; pos < size; pos++) {
junyulaic4e591a2018-11-26 22:36:10 +0900616 uint8_t *byte = ((uint8_t *)data) + pos;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900617 for (int shift = 0; shift < 8; shift++) {
618 onebits += (*byte >> shift) & 1;
619 }
620 }
621 return onebits;
622}
623
624TEST_F(ClatdTest, TestCountOnebits) {
625 uint64_t i;
626 i = 1;
627 ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
628 i <<= 61;
629 ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
junyulaic4e591a2018-11-26 22:36:10 +0900630 i |= ((uint64_t)1 << 33);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900631 ASSERT_EQ(2, count_onebits(&i, sizeof(i)));
632 i = 0xf1000202020000f0;
633 ASSERT_EQ(5 + 1 + 1 + 1 + 4, count_onebits(&i, sizeof(i)));
634}
635
636TEST_F(ClatdTest, TestGenIIDConfigured) {
637 struct in6_addr myaddr, expected;
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800638 Global_Clatd_Config.use_dynamic_iid = 0;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900639 ASSERT_TRUE(inet_pton(AF_INET6, "::bad:ace:d00d", &Global_Clatd_Config.ipv6_host_id));
640 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:0:bad:ace:d00d", &expected));
641 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &myaddr));
642 config_generate_local_ipv6_subnet(&myaddr);
643 expect_ipv6_addr_equal(&expected, &myaddr);
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800644
645 Global_Clatd_Config.use_dynamic_iid = 1;
646 config_generate_local_ipv6_subnet(&myaddr);
647 EXPECT_FALSE(IN6_ARE_ADDR_EQUAL(&expected, &myaddr));
Lorenzo Colitti98089522014-10-09 22:29:45 +0900648}
649
650TEST_F(ClatdTest, TestGenIIDRandom) {
651 struct in6_addr interface_ipv6;
652 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &interface_ipv6));
653 Global_Clatd_Config.ipv6_host_id = in6addr_any;
654
655 // Generate a boatload of random IIDs.
junyulaic4e591a2018-11-26 22:36:10 +0900656 int onebits = 0;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900657 uint64_t prev_iid = 0;
658 for (int i = 0; i < 100000; i++) {
junyulaic4e591a2018-11-26 22:36:10 +0900659 struct in6_addr myaddr = interface_ipv6;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900660
661 config_generate_local_ipv6_subnet(&myaddr);
662
663 // Check the generated IP address is in the same prefix as the interface IPv6 address.
664 EXPECT_TRUE(ipv6_prefix_equal(&interface_ipv6, &myaddr));
665
666 // Check that consecutive IIDs are not the same.
junyulaic4e591a2018-11-26 22:36:10 +0900667 uint64_t iid = *(uint64_t *)(&myaddr.s6_addr[8]);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900668 ASSERT_TRUE(iid != prev_iid)
669 << "Two consecutive random IIDs are the same: "
670 << std::showbase << std::hex
671 << iid << "\n";
672 prev_iid = iid;
673
674 // Check that the IID is checksum-neutral with the NAT64 prefix and the
675 // local prefix.
junyulaic4e591a2018-11-26 22:36:10 +0900676 struct in_addr *ipv4addr = &Global_Clatd_Config.ipv4_local_subnet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900677 struct in6_addr *plat_subnet = &Global_Clatd_Config.plat_subnet;
678
679 uint16_t c1 = ip_checksum_finish(ip_checksum_add(0, ipv4addr, sizeof(*ipv4addr)));
680 uint16_t c2 = ip_checksum_finish(ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
681 ip_checksum_add(0, &myaddr, sizeof(myaddr)));
682
683 if (c1 != c2) {
684 char myaddr_str[INET6_ADDRSTRLEN], plat_str[INET6_ADDRSTRLEN], ipv4_str[INET6_ADDRSTRLEN];
685 inet_ntop(AF_INET6, &myaddr, myaddr_str, sizeof(myaddr_str));
686 inet_ntop(AF_INET6, plat_subnet, plat_str, sizeof(plat_str));
687 inet_ntop(AF_INET, ipv4addr, ipv4_str, sizeof(ipv4_str));
688 FAIL()
689 << "Bad IID: " << myaddr_str
690 << " not checksum-neutral with " << ipv4_str << " and " << plat_str
691 << std::showbase << std::hex
692 << "\n IPv4 checksum: " << c1
693 << "\n IPv6 checksum: " << c2
694 << "\n";
695 }
696
697 // Check that IIDs are roughly random and use all the bits by counting the
698 // total number of bits set to 1 in a random sample of 100000 generated IIDs.
699 onebits += count_onebits(&iid, sizeof(iid));
700 }
701 EXPECT_LE(3190000, onebits);
702 EXPECT_GE(3210000, onebits);
703}
704
Lorenzo Colitti798f9932014-10-31 21:54:33 +0900705extern "C" addr_free_func config_is_ipv4_address_free;
706int never_free(in_addr_t /* addr */) { return 0; }
707int always_free(in_addr_t /* addr */) { return 1; }
708int only2_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 2; }
709int over6_free(in_addr_t addr) { return (ntohl(addr) & 0xff) >= 6; }
710int only10_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; }
711
712TEST_F(ClatdTest, SelectIPv4Address) {
713 struct in_addr addr;
714
715 inet_pton(AF_INET, kIPv4LocalAddr, &addr);
716
717 addr_free_func orig_config_is_ipv4_address_free = config_is_ipv4_address_free;
718
719 // If no addresses are free, return INADDR_NONE.
720 config_is_ipv4_address_free = never_free;
721 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
722 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 16));
723
724 // If the configured address is free, pick that. But a prefix that's too big is invalid.
725 config_is_ipv4_address_free = always_free;
726 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 29));
727 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 20));
728 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 15));
729
730 // A prefix length of 32 works, but anything above it is invalid.
731 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 32));
732 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 33));
733
734 // If another address is free, pick it.
735 config_is_ipv4_address_free = over6_free;
736 EXPECT_EQ(inet_addr("192.0.0.6"), config_select_ipv4_address(&addr, 29));
737
738 // Check that we wrap around to addresses that are lower than the first address.
739 config_is_ipv4_address_free = only2_free;
740 EXPECT_EQ(inet_addr("192.0.0.2"), config_select_ipv4_address(&addr, 29));
741 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 30));
742
743 // If a free address exists outside the prefix, we don't pick it.
744 config_is_ipv4_address_free = only10_free;
745 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
746 EXPECT_EQ(inet_addr("192.0.0.10"), config_select_ipv4_address(&addr, 24));
747
748 // Now try using the real function which sees if IP addresses are free using bind().
749 // Assume that the machine running the test has the address 127.0.0.1, but not 8.8.8.8.
750 config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
junyulaic4e591a2018-11-26 22:36:10 +0900751 addr.s_addr = inet_addr("8.8.8.8");
Lorenzo Colitti798f9932014-10-31 21:54:33 +0900752 EXPECT_EQ(inet_addr("8.8.8.8"), config_select_ipv4_address(&addr, 29));
753
754 addr.s_addr = inet_addr("127.0.0.1");
755 EXPECT_EQ(inet_addr("127.0.0.2"), config_select_ipv4_address(&addr, 29));
756}
757
Lorenzo Colitti98089522014-10-09 22:29:45 +0900758TEST_F(ClatdTest, DataSanitycheck) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900759 // Sanity checks the data.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800760 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900761 ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
762
Brian Carlstromfcac4102014-02-24 20:03:01 -0800763 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900764 ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
765
Brian Carlstromfcac4102014-02-24 20:03:01 -0800766 uint8_t udp_header[] = { UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900767 ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
768
769 // Sanity checks check_packet.
770 struct udphdr *udp;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800771 uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900772 udp = (struct udphdr *)(v4_udp_packet + sizeof(struct iphdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900773 fix_udp_checksum(v4_udp_packet);
774 ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
775 check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
776
Brian Carlstromfcac4102014-02-24 20:03:01 -0800777 uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900778 udp = (struct udphdr *)(v6_udp_packet + sizeof(struct ip6_hdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900779 fix_udp_checksum(v6_udp_packet);
780 ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
781 check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
782
Brian Carlstromfcac4102014-02-24 20:03:01 -0800783 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900784 check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
785
Brian Carlstromfcac4102014-02-24 20:03:01 -0800786 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900787 check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
788
789 // Sanity checks reassemble_packet.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800790 uint8_t reassembled[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900791 size_t total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900792 reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), reassembled,
793 &total_length, "Reassembly sanity check");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900794 check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
795 ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
junyulaic4e591a2018-11-26 22:36:10 +0900796 ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *)reassembled))
797 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900798 check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
799
800 total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900801 reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments), reassembled,
802 &total_length, "IPv6 reassembly sanity check");
803 ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *)reassembled, total_length))
804 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900805 check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
806}
807
808TEST_F(ClatdTest, PseudoChecksum) {
809 uint32_t pseudo_checksum;
810
junyulaic4e591a2018-11-26 22:36:10 +0900811 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800812 uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900813 pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *)v4_header, UDP_LEN);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900814 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
815 ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900816 << "ipv4_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900817
junyulaic4e591a2018-11-26 22:36:10 +0900818 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800819 uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900820 pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *)v6_header, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900821 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
822 ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900823 << "ipv6_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900824}
825
826TEST_F(ClatdTest, TransportChecksum) {
junyulaic4e591a2018-11-26 22:36:10 +0900827 uint8_t udphdr[] = { UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800828 uint8_t payload[] = { PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900829 EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
junyulaic4e591a2018-11-26 22:36:10 +0900830 << "UDP partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900831 EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
junyulaic4e591a2018-11-26 22:36:10 +0900832 << "Payload partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900833
junyulaic4e591a2018-11-26 22:36:10 +0900834 uint8_t ip[] = { IPV4_UDP_HEADER };
835 uint8_t ip6[] = { IPV6_UDP_HEADER };
836 uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *)ip, UDP_LEN);
837 uint32_t ipv6_pseudo_sum =
838 ipv6_pseudo_header_checksum((struct ip6_hdr *)ip6, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900839
Ben Cheng932614e2014-04-02 17:00:26 -0700840 EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum) << "IPv4 pseudo-checksum sanity check\n";
841 EXPECT_EQ(0x2644bU, ipv6_pseudo_sum) << "IPv6 pseudo-checksum sanity check\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900842 EXPECT_EQ(
843 kUdpV4Checksum,
844 ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
845 << "Unexpected UDP/IPv4 checksum\n";
846 EXPECT_EQ(
847 kUdpV6Checksum,
848 ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
849 << "Unexpected UDP/IPv6 checksum\n";
850
851 EXPECT_EQ(kUdpV6Checksum,
852 ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
853 << "Adjust IPv4/UDP checksum to IPv6\n";
854 EXPECT_EQ(kUdpV4Checksum,
855 ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
856 << "Adjust IPv6/UDP checksum to IPv4\n";
857}
858
859TEST_F(ClatdTest, AdjustChecksum) {
860 struct checksum_data {
861 uint16_t checksum;
862 uint32_t old_hdr_sum;
863 uint32_t new_hdr_sum;
864 uint16_t result;
865 } DATA[] = {
866 { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
867 { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
868 { 0xdd2f, 0x5555, 0x3285, 0x0000 },
869 { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
870 { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
871 };
Chih-Hung Hsieh05ff5082014-08-26 10:46:26 -0700872 unsigned i = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900873
874 for (i = 0; i < ARRAYSIZE(DATA); i++) {
875 struct checksum_data *data = DATA + i;
876 uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
877 EXPECT_EQ(result, data->result)
878 << "Incorrect checksum" << std::showbase << std::hex
879 << "\n Expected: " << data->result
880 << "\n Actual: " << result
881 << "\n checksum=" << data->checksum
882 << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
883 }
884}
885
886TEST_F(ClatdTest, Translate) {
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900887 // This test uses hardcoded packets so the clatd address must be fixed.
888 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
889
Brian Carlstromfcac4102014-02-24 20:03:01 -0800890 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
891 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900892 fix_udp_checksum(udp_ipv4);
893 fix_udp_checksum(udp_ipv6);
894 check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
895 "UDP/IPv4 -> UDP/IPv6 translation");
896 check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
897 "UDP/IPv6 -> UDP/IPv4 translation");
898
Brian Carlstromfcac4102014-02-24 20:03:01 -0800899 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
900 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900901 check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
902 "ICMP->ICMPv6 translation");
903 check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
904 "ICMPv6->ICMP translation");
905}
906
907TEST_F(ClatdTest, Fragmentation) {
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900908 // This test uses hardcoded packets so the clatd address must be fixed.
909 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
910
junyulaic4e591a2018-11-26 22:36:10 +0900911 check_fragment_translation(kIPv4Fragments, kIPv4FragLengths, kIPv6Fragments, kIPv6FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900912 ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
913
junyulaic4e591a2018-11-26 22:36:10 +0900914 check_fragment_translation(kIPv6Fragments, kIPv6FragLengths, kIPv4Fragments, kIPv4FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900915 ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
916}
Lorenzo Colitti98089522014-10-09 22:29:45 +0900917
918void check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
919 size_t expected_len, const char *msg) {
920 uint8_t translated[MAXMTU];
921 size_t translated_len = sizeof(translated);
922 do_translate_packet(original, original_len, translated, &translated_len, msg);
923 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
924 // do_translate_packet already checks packets for validity and verifies the checksum.
junyulaic4e591a2018-11-26 22:36:10 +0900925 int original_check = get_transport_checksum(original);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900926 int translated_check = get_transport_checksum(translated);
927 ASSERT_NE(-1, original_check);
928 ASSERT_NE(-1, translated_check);
929 ASSERT_EQ(original_check, translated_check)
junyulaic4e591a2018-11-26 22:36:10 +0900930 << "Not checksum neutral: original and translated checksums differ\n";
Lorenzo Colitti98089522014-10-09 22:29:45 +0900931}
932
933TEST_F(ClatdTest, TranslateChecksumNeutral) {
934 // Generate a random clat IPv6 address and check that translation is checksum-neutral.
935 Global_Clatd_Config.ipv6_host_id = in6addr_any;
936 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
937 &Global_Clatd_Config.ipv6_local_subnet));
938 config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900939 ASSERT_NE(htonl((uint32_t)0x00000464), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
junyulaic4e591a2018-11-26 22:36:10 +0900940 ASSERT_NE((uint32_t)0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900941
942 // Check that translating UDP packets is checksum-neutral. First, IPv4.
943 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
944 fix_udp_checksum(udp_ipv4);
945 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
946 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
947
948 // Now try IPv6.
949 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
950 // The test packet uses the static IID, not the random IID. Fix up the source address.
junyulaic4e591a2018-11-26 22:36:10 +0900951 struct ip6_hdr *ip6 = (struct ip6_hdr *)udp_ipv6;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900952 memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
953 fix_udp_checksum(udp_ipv6);
954 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
955 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
956}
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900957
958TEST_F(ClatdTest, GetInterfaceIp) {
959 union anyip *ip = getinterface_ip(sTun.name().c_str(), AF_INET6);
960 ASSERT_NE(nullptr, ip);
961 in6_addr expected = sTun.srcAddr();
962 in6_addr actual = ip->ip6;
963 expect_ipv6_addr_equal(&expected, &actual);
964}
965
966TEST_F(ClatdTest, UpdateIpv6Address) {
967 // Create some fake but realistic-looking sockets so update_clat_ipv6_address doesn't balk.
968 struct tun_data tunnel = {
969 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
970 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
971 };
972
973 // Run update_clat_ipv6_address with no local IID yet picked.
974 ASSERT_TRUE(IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_local_subnet));
975 ASSERT_EQ(1, update_clat_ipv6_address(&tunnel, sTun.name().c_str()));
976
977 // Check that it generated an IID in the same prefix as the address assigned to the interface,
978 // and that the IID is not the default IID.
979 in6_addr addr = sTun.srcAddr();
980 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &addr));
981 EXPECT_FALSE(IN6_ARE_ADDR_EQUAL(&Global_Clatd_Config.ipv6_local_subnet, &addr));
982 EXPECT_NE(htonl((uint32_t)0x00000464), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
983 EXPECT_NE((uint32_t)0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
984
985 // Check that the packet socket is bound to the interface. We can't check the socket filter
986 // because there is no way to fetch it from the kernel.
987 sockaddr_ll sll;
988 socklen_t len = sizeof(sll);
989 ASSERT_EQ(0, getsockname(tunnel.read_fd6, reinterpret_cast<sockaddr *>(&sll), &len));
990 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
991 EXPECT_EQ(sll.sll_ifindex, sTun.ifindex());
992}