blob: 5de7b634296b80aedac1831ed2f2ab7cd5589dcb [file] [log] [blame]
Lorenzo Colittif3beefc2014-02-14 13:19:27 +09001/*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * clatd_test.cpp - unit tests for clatd
17 */
18
19#include <iostream>
20
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090021#include <arpa/inet.h>
Lorenzo Colitti98089522014-10-09 22:29:45 +090022#include <netinet/in6.h>
junyulaic4e591a2018-11-26 22:36:10 +090023#include <stdio.h>
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090024#include <sys/uio.h>
25
26#include <gtest/gtest.h>
Lorenzo Colitti66deecd2019-01-04 12:27:27 +090027
28#include "netutils/ifc.h"
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090029#include "tun_interface.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090030
31extern "C" {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090032#include "clatd.h"
junyulaic4e591a2018-11-26 22:36:10 +090033#include "config.h"
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090034#include "getaddr.h"
Lorenzo Colitti98de5952019-01-20 11:45:03 +090035#include "netutils/checksum.h"
junyulaic4e591a2018-11-26 22:36:10 +090036#include "translate.h"
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090037#include "tun.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090038}
39
40// For convenience.
41#define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0])
42
Lorenzo Colitti72f770c2019-01-04 15:00:28 +090043using android::net::TunInterface;
44
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090045// Default translation parameters.
junyulaic4e591a2018-11-26 22:36:10 +090046static const char kIPv4LocalAddr[] = "192.0.0.4";
47static const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090048static const char kIPv6PlatSubnet[] = "64:ff9b::";
49
junyulaic4e591a2018-11-26 22:36:10 +090050// clang-format off
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090051// Test packet portions. Defined as macros because it's easy to concatenate them to make packets.
52#define IPV4_HEADER(p, c1, c2) \
53 0x45, 0x00, 0, 41, /* Version=4, IHL=5, ToS=0x80, len=41 */ \
54 0x00, 0x00, 0x40, 0x00, /* ID=0x0000, flags=IP_DF, offset=0 */ \
55 55, (p), (c1), (c2), /* TTL=55, protocol=p, checksum=c1,c2 */ \
56 192, 0, 0, 4, /* Src=192.0.0.4 */ \
57 8, 8, 8, 8, /* Dst=8.8.8.8 */
58#define IPV4_UDP_HEADER IPV4_HEADER(IPPROTO_UDP, 0x73, 0xb0)
59#define IPV4_ICMP_HEADER IPV4_HEADER(IPPROTO_ICMP, 0x73, 0xc0)
60
61#define IPV6_HEADER(p) \
62 0x60, 0x00, 0, 0, /* Version=6, tclass=0x00, flowlabel=0 */ \
63 0, 21, (p), 55, /* plen=11, nxthdr=p, hlim=55 */ \
64 0x20, 0x01, 0x0d, 0xb8, /* Src=2001:db8:0:b11::464 */ \
65 0x00, 0x00, 0x0b, 0x11, \
66 0x00, 0x00, 0x00, 0x00, \
67 0x00, 0x00, 0x04, 0x64, \
68 0x00, 0x64, 0xff, 0x9b, /* Dst=64:ff9b::8.8.8.8 */ \
69 0x00, 0x00, 0x00, 0x00, \
70 0x00, 0x00, 0x00, 0x00, \
71 0x08, 0x08, 0x08, 0x08,
72#define IPV6_UDP_HEADER IPV6_HEADER(IPPROTO_UDP)
73#define IPV6_ICMPV6_HEADER IPV6_HEADER(IPPROTO_ICMPV6)
74
75#define UDP_LEN 21
76#define UDP_HEADER \
77 0xc8, 0x8b, 0, 53, /* Port 51339->53 */ \
78 0x00, UDP_LEN, 0, 0, /* Length 21, checksum empty for now */
79
80#define PAYLOAD 'H', 'e', 'l', 'l', 'o', ' ', 0x4e, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0x00
81
82#define IPV4_PING \
83 0x08, 0x00, 0x88, 0xd0, /* Type 8, code 0, checksum 0x88d0 */ \
84 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
85
86#define IPV6_PING \
87 0x80, 0x00, 0xc3, 0x42, /* Type 128, code 0, checksum 0xc342 */ \
88 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
89
90// Macros to return pseudo-headers from packets.
91#define IPV4_PSEUDOHEADER(ip, tlen) \
92 ip[12], ip[13], ip[14], ip[15], /* Source address */ \
93 ip[16], ip[17], ip[18], ip[19], /* Destination address */ \
94 0, ip[9], /* 0, protocol */ \
95 ((tlen) >> 16) & 0xff, (tlen) & 0xff, /* Transport length */
96
97#define IPV6_PSEUDOHEADER(ip6, protocol, tlen) \
98 ip6[8], ip6[9], ip6[10], ip6[11], /* Source address */ \
99 ip6[12], ip6[13], ip6[14], ip6[15], \
100 ip6[16], ip6[17], ip6[18], ip6[19], \
101 ip6[20], ip6[21], ip6[22], ip6[23], \
102 ip6[24], ip6[25], ip6[26], ip6[27], /* Destination address */ \
103 ip6[28], ip6[29], ip6[30], ip6[31], \
104 ip6[32], ip6[33], ip6[34], ip6[35], \
105 ip6[36], ip6[37], ip6[38], ip6[39], \
106 ((tlen) >> 24) & 0xff, /* Transport length */ \
107 ((tlen) >> 16) & 0xff, \
108 ((tlen) >> 8) & 0xff, \
109 (tlen) & 0xff, \
110 0, 0, 0, (protocol),
111
112// A fragmented DNS request.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800113static const uint8_t kIPv4Frag1[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900114 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x00, 0x40, 0x11,
115 0x8c, 0x6d, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
116 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
117 0x01, 0x00, 0x00, 0x01, 0x00, 0x00
118};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800119static const uint8_t kIPv4Frag2[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900120 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x02, 0x40, 0x11,
121 0x8c, 0x6b, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
122 0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06,
123 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65
124};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800125static const uint8_t kIPv4Frag3[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900126 0x45, 0x00, 0x00, 0x1d, 0xfe, 0x47, 0x00, 0x04, 0x40, 0x11,
127 0xac, 0x70, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
128 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
129};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800130static const uint8_t *kIPv4Fragments[] = { kIPv4Frag1, kIPv4Frag2, kIPv4Frag3 };
131static const size_t kIPv4FragLengths[] = { sizeof(kIPv4Frag1), sizeof(kIPv4Frag2),
132 sizeof(kIPv4Frag3) };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900133
Brian Carlstromfcac4102014-02-24 20:03:01 -0800134static const uint8_t kIPv6Frag1[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900135 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
136 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
139 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x47, 0x14, 0x5d,
140 0x00, 0x35, 0x00, 0x29, 0xeb, 0x91, 0x50, 0x47, 0x01, 0x00,
141 0x00, 0x01, 0x00, 0x00
142};
143
Brian Carlstromfcac4102014-02-24 20:03:01 -0800144static const uint8_t kIPv6Frag2[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900145 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
146 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
149 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0xfe, 0x47, 0x00, 0x00,
150 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f,
151 0x6f, 0x67, 0x6c, 0x65
152};
153
Brian Carlstromfcac4102014-02-24 20:03:01 -0800154static const uint8_t kIPv6Frag3[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900155 0x60, 0x00, 0x00, 0x00, 0x00, 0x11, 0x2c, 0x40, 0x20, 0x01,
156 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
159 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0xfe, 0x47, 0x03, 0x63,
160 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
161};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800162static const uint8_t *kIPv6Fragments[] = { kIPv6Frag1, kIPv6Frag2, kIPv6Frag3 };
163static const size_t kIPv6FragLengths[] = { sizeof(kIPv6Frag1), sizeof(kIPv6Frag2),
164 sizeof(kIPv6Frag3) };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900165
Brian Carlstromfcac4102014-02-24 20:03:01 -0800166static const uint8_t kReassembledIPv4[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900167 0x45, 0x00, 0x00, 0x3d, 0xfe, 0x47, 0x00, 0x00, 0x40, 0x11,
168 0xac, 0x54, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
169 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
170 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67,
172 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
173 0x01
174};
junyulaic4e591a2018-11-26 22:36:10 +0900175// clang-format on
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900176
177// Expected checksums.
178static const uint32_t kUdpPartialChecksum = 0xd5c8;
179static const uint32_t kPayloadPartialChecksum = 0x31e9c;
180static const uint16_t kUdpV4Checksum = 0xd0c7;
181static const uint16_t kUdpV6Checksum = 0xa74a;
182
Brian Carlstromfcac4102014-02-24 20:03:01 -0800183uint8_t ip_version(const uint8_t *packet) {
184 uint8_t version = packet[0] >> 4;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900185 return version;
186}
187
188int is_ipv4_fragment(struct iphdr *ip) {
189 // A packet is a fragment if its fragment offset is nonzero or if the MF flag is set.
190 return ntohs(ip->frag_off) & (IP_OFFMASK | IP_MF);
191}
192
193int is_ipv6_fragment(struct ip6_hdr *ip6, size_t len) {
194 if (ip6->ip6_nxt != IPPROTO_FRAGMENT) {
195 return 0;
196 }
junyulaic4e591a2018-11-26 22:36:10 +0900197 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900198 return len >= sizeof(*ip6) + sizeof(*frag) &&
junyulaic4e591a2018-11-26 22:36:10 +0900199 (frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900200}
201
202int ipv4_fragment_offset(struct iphdr *ip) {
203 return ntohs(ip->frag_off) & IP_OFFMASK;
204}
205
206int ipv6_fragment_offset(struct ip6_frag *frag) {
207 return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3);
208}
209
Brian Carlstromfcac4102014-02-24 20:03:01 -0800210void check_packet(const uint8_t *packet, size_t len, const char *msg) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900211 void *payload;
junyulaic4e591a2018-11-26 22:36:10 +0900212 size_t payload_length = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900213 uint32_t pseudo_checksum = 0;
junyulaic4e591a2018-11-26 22:36:10 +0900214 uint8_t protocol = 0;
215 int version = ip_version(packet);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900216 switch (version) {
217 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900218 struct iphdr *ip = (struct iphdr *)packet;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900219 ASSERT_GE(len, sizeof(*ip)) << msg << ": IPv4 packet shorter than IPv4 header\n";
220 EXPECT_EQ(5, ip->ihl) << msg << ": Unsupported IP header length\n";
221 EXPECT_EQ(len, ntohs(ip->tot_len)) << msg << ": Incorrect IPv4 length\n";
222 EXPECT_EQ(0, ip_checksum(ip, sizeof(*ip))) << msg << ": Incorrect IP checksum\n";
223 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900224 payload = ip + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900225 if (!is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900226 payload_length = len - sizeof(*ip);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900227 pseudo_checksum = ipv4_pseudo_header_checksum(ip, payload_length);
228 }
229 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP)
junyulaic4e591a2018-11-26 22:36:10 +0900230 << msg << ": Unsupported IPv4 protocol " << protocol << "\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900231 break;
232 }
233 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900234 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900235 ASSERT_GE(len, sizeof(*ip6)) << msg << ": IPv6 packet shorter than IPv6 header\n";
236 EXPECT_EQ(len - sizeof(*ip6), htons(ip6->ip6_plen)) << msg << ": Incorrect IPv6 length\n";
237
238 if (ip6->ip6_nxt == IPPROTO_FRAGMENT) {
junyulaic4e591a2018-11-26 22:36:10 +0900239 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900240 ASSERT_GE(len, sizeof(*ip6) + sizeof(*frag))
junyulaic4e591a2018-11-26 22:36:10 +0900241 << msg << ": IPv6 fragment: short fragment header\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900242 protocol = frag->ip6f_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900243 payload = frag + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900244 // Even though the packet has a Fragment header, it might not be a fragment.
245 if (!is_ipv6_fragment(ip6, len)) {
246 payload_length = len - sizeof(*ip6) - sizeof(*frag);
247 }
248 } else {
249 // Since there are no extension headers except Fragment, this must be the payload.
junyulaic4e591a2018-11-26 22:36:10 +0900250 protocol = ip6->ip6_nxt;
251 payload = ip6 + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900252 payload_length = len - sizeof(*ip6);
253 }
254 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMPV6)
junyulaic4e591a2018-11-26 22:36:10 +0900255 << msg << ": Unsupported IPv6 next header " << protocol;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900256 if (payload_length) {
257 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, payload_length, protocol);
258 }
259 break;
260 }
261 default:
262 FAIL() << msg << ": Unsupported IP version " << version << "\n";
263 return;
264 }
265
266 // If we understand the payload, verify the checksum.
267 if (payload_length) {
268 uint16_t checksum;
junyulaic4e591a2018-11-26 22:36:10 +0900269 switch (protocol) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900270 case IPPROTO_UDP:
271 case IPPROTO_TCP:
272 case IPPROTO_ICMPV6:
273 checksum = ip_checksum_finish(ip_checksum_add(pseudo_checksum, payload, payload_length));
274 break;
275 case IPPROTO_ICMP:
276 checksum = ip_checksum(payload, payload_length);
277 break;
278 default:
279 checksum = 0; // Don't check.
280 break;
281 }
282 EXPECT_EQ(0, checksum) << msg << ": Incorrect transport checksum\n";
283 }
284
285 if (protocol == IPPROTO_UDP) {
junyulaic4e591a2018-11-26 22:36:10 +0900286 struct udphdr *udp = (struct udphdr *)payload;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900287 EXPECT_NE(0, udp->check) << msg << ": UDP checksum 0 should be 0xffff";
288 // If this is not a fragment, check the UDP length field.
289 if (payload_length) {
290 EXPECT_EQ(payload_length, ntohs(udp->len)) << msg << ": Incorrect UDP length\n";
291 }
292 }
293}
294
Brian Carlstromfcac4102014-02-24 20:03:01 -0800295void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int numpackets,
296 uint8_t *reassembled, size_t *reassembled_len, const char *msg) {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900297 struct iphdr *ip = nullptr;
298 struct ip6_hdr *ip6 = nullptr;
junyulaic4e591a2018-11-26 22:36:10 +0900299 size_t total_length, pos = 0;
Ben Cheng932614e2014-04-02 17:00:26 -0700300 uint8_t protocol = 0;
junyulaic4e591a2018-11-26 22:36:10 +0900301 uint8_t version = ip_version(fragments[0]);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900302
303 for (int i = 0; i < numpackets; i++) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800304 const uint8_t *packet = fragments[i];
junyulaic4e591a2018-11-26 22:36:10 +0900305 int len = lengths[i];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900306 int headersize, payload_offset;
307
308 ASSERT_EQ(ip_version(packet), version) << msg << ": Inconsistent fragment versions\n";
309 check_packet(packet, len, "Fragment sanity check");
310
311 switch (version) {
312 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900313 struct iphdr *ip_orig = (struct iphdr *)packet;
314 headersize = sizeof(*ip_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900315 ASSERT_TRUE(is_ipv4_fragment(ip_orig))
junyulaic4e591a2018-11-26 22:36:10 +0900316 << msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n";
317 ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip) : 0))
318 << msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900319
junyulaic4e591a2018-11-26 22:36:10 +0900320 headersize = sizeof(*ip_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900321 payload_offset = headersize;
322 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900323 ip = (struct iphdr *)reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900324 }
325 break;
326 }
327 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900328 struct ip6_hdr *ip6_orig = (struct ip6_hdr *)packet;
329 struct ip6_frag *frag = (struct ip6_frag *)(ip6_orig + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900330 ASSERT_TRUE(is_ipv6_fragment(ip6_orig, len))
junyulaic4e591a2018-11-26 22:36:10 +0900331 << msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n";
332 ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6) : 0))
333 << msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900334
junyulaic4e591a2018-11-26 22:36:10 +0900335 headersize = sizeof(*ip6_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900336 payload_offset = sizeof(*ip6_orig) + sizeof(*frag);
337 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900338 ip6 = (struct ip6_hdr *)reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900339 protocol = frag->ip6f_nxt;
340 }
341 break;
342 }
343 default:
344 FAIL() << msg << ": Invalid IP version << " << version;
345 }
346
347 // If this is the first fragment, copy the header.
348 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900349 ASSERT_LT(headersize, (int)*reassembled_len) << msg << ": Reassembly buffer too small\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900350 memcpy(reassembled, packet, headersize);
351 total_length = headersize;
352 pos += headersize;
353 }
354
355 // Copy the payload.
356 int payload_length = len - payload_offset;
357 total_length += payload_length;
Ben Cheng932614e2014-04-02 17:00:26 -0700358 ASSERT_LT(total_length, *reassembled_len) << msg << ": Reassembly buffer too small\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900359 memcpy(reassembled + pos, packet + payload_offset, payload_length);
360 pos += payload_length;
361 }
362
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900363 // Fix up the reassembled headers to reflect fragmentation and length (and IPv4 checksum).
364 ASSERT_EQ(total_length, pos) << msg << ": Reassembled packet length incorrect\n";
365 if (ip) {
366 ip->frag_off &= ~htons(IP_MF);
367 ip->tot_len = htons(total_length);
junyulaic4e591a2018-11-26 22:36:10 +0900368 ip->check = 0;
369 ip->check = ip_checksum(ip, sizeof(*ip));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900370 ASSERT_FALSE(is_ipv4_fragment(ip)) << msg << ": reassembled IPv4 packet is a fragment!\n";
371 }
372 if (ip6) {
junyulaic4e591a2018-11-26 22:36:10 +0900373 ip6->ip6_nxt = protocol;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900374 ip6->ip6_plen = htons(total_length - sizeof(*ip6));
375 ASSERT_FALSE(is_ipv6_fragment(ip6, ip6->ip6_plen))
junyulaic4e591a2018-11-26 22:36:10 +0900376 << msg << ": reassembled IPv6 packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900377 }
378
379 *reassembled_len = total_length;
380}
381
Lorenzo Colitti98089522014-10-09 22:29:45 +0900382void check_data_matches(const void *expected, const void *actual, size_t len, const char *msg) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900383 if (memcmp(expected, actual, len)) {
384 // Hex dump, 20 bytes per line, one space between bytes (1 byte = 3 chars), indented by 4.
385 int hexdump_len = len * 3 + (len / 20 + 1) * 5;
386 char expected_hexdump[hexdump_len], actual_hexdump[hexdump_len];
387 unsigned pos = 0;
388 for (unsigned i = 0; i < len; i++) {
389 if (i % 20 == 0) {
George Burgess IV2dcca6f2016-02-24 15:55:54 -0800390 snprintf(expected_hexdump + pos, hexdump_len - pos, "\n ");
391 snprintf(actual_hexdump + pos, hexdump_len - pos, "\n ");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900392 pos += 4;
393 }
junyulaic4e591a2018-11-26 22:36:10 +0900394 snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)expected)[i]);
395 snprintf(actual_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)actual)[i]);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900396 pos += 3;
397 }
Lorenzo Colitti98089522014-10-09 22:29:45 +0900398 FAIL() << msg << ": Data doesn't match"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900399 << "\n Expected:" << (char *) expected_hexdump
400 << "\n Actual:" << (char *) actual_hexdump << "\n";
401 }
402}
403
junyulaic4e591a2018-11-26 22:36:10 +0900404void fix_udp_checksum(uint8_t *packet) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900405 uint32_t pseudo_checksum;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800406 uint8_t version = ip_version(packet);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900407 struct udphdr *udp;
408 switch (version) {
409 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900410 struct iphdr *ip = (struct iphdr *)packet;
411 udp = (struct udphdr *)(ip + 1);
412 pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900413 break;
414 }
415 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900416 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
417 udp = (struct udphdr *)(ip6 + 1);
418 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900419 break;
420 }
421 default:
422 FAIL() << "unsupported IP version" << version << "\n";
423 return;
junyulaic4e591a2018-11-26 22:36:10 +0900424 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900425
426 udp->check = 0;
427 udp->check = ip_checksum_finish(ip_checksum_add(pseudo_checksum, udp, ntohs(udp->len)));
428}
429
Lorenzo Colittice140882014-06-02 21:20:40 +0900430// Testing stub for send_rawv6. The real version uses sendmsg() with a
431// destination IPv6 address, and attempting to call that on our test socketpair
432// fd results in EINVAL.
junyulaic4e591a2018-11-26 22:36:10 +0900433extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) { writev(fd, out, iov_len); }
Lorenzo Colittice140882014-06-02 21:20:40 +0900434
Brian Carlstromfcac4102014-02-24 20:03:01 -0800435void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *out, size_t *outlen,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900436 const char *msg) {
437 int fds[2];
438 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, fds)) {
439 abort();
440 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900441
442 char foo[512];
443 snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg);
444 check_packet(original, original_len, foo);
445
Lorenzo Colittie24982e2014-06-02 15:49:36 +0900446 int read_fd, write_fd;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900447 uint16_t expected_proto;
448 int version = ip_version(original);
449 switch (version) {
450 case 4:
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900451 expected_proto = htons(ETH_P_IPV6);
junyulaic4e591a2018-11-26 22:36:10 +0900452 read_fd = fds[1];
453 write_fd = fds[0];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900454 break;
455 case 6:
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900456 expected_proto = htons(ETH_P_IP);
junyulaic4e591a2018-11-26 22:36:10 +0900457 read_fd = fds[0];
458 write_fd = fds[1];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900459 break;
460 default:
461 FAIL() << msg << ": Unsupported IP version " << version << "\n";
462 break;
463 }
464
Lorenzo Colittie24982e2014-06-02 15:49:36 +0900465 translate_packet(write_fd, (version == 4), original, original_len);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900466
Lorenzo Colitti98089522014-10-09 22:29:45 +0900467 snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
Lorenzo Colittice140882014-06-02 21:20:40 +0900468 if (version == 6) {
469 // Translating to IPv4. Expect a tun header.
470 struct tun_pi new_tun_header;
471 struct iovec iov[] = {
472 { &new_tun_header, sizeof(new_tun_header) },
junyulaic4e591a2018-11-26 22:36:10 +0900473 { out, *outlen },
Lorenzo Colittice140882014-06-02 21:20:40 +0900474 };
junyulaic4e591a2018-11-26 22:36:10 +0900475
Lorenzo Colittice140882014-06-02 21:20:40 +0900476 int len = readv(read_fd, iov, 2);
junyulaic4e591a2018-11-26 22:36:10 +0900477 if (len > (int)sizeof(new_tun_header)) {
478 ASSERT_LT((size_t)len, *outlen) << msg << ": Translated packet buffer too small\n";
Lorenzo Colittice140882014-06-02 21:20:40 +0900479 EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
480 *outlen = len - sizeof(new_tun_header);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900481 check_packet(out, *outlen, msg);
Lorenzo Colittice140882014-06-02 21:20:40 +0900482 } else {
Lorenzo Colitti98089522014-10-09 22:29:45 +0900483 FAIL() << msg << ": Packet was not translated: len=" << len;
Lorenzo Colittice140882014-06-02 21:20:40 +0900484 *outlen = 0;
485 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900486 } else {
Lorenzo Colittice140882014-06-02 21:20:40 +0900487 // Translating to IPv6. Expect raw packet.
488 *outlen = read(read_fd, out, *outlen);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900489 check_packet(out, *outlen, msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900490 }
491}
492
junyulaic4e591a2018-11-26 22:36:10 +0900493void check_translated_packet(const uint8_t *original, size_t original_len, const uint8_t *expected,
494 size_t expected_len, const char *msg) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800495 uint8_t translated[MAXMTU];
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);
500}
501
Brian Carlstromfcac4102014-02-24 20:03:01 -0800502void check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
503 const uint8_t *expected[], const size_t expected_lengths[],
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900504 int numfragments, const char *msg) {
505 for (int i = 0; i < numfragments; i++) {
506 // Check that each of the fragments translates as expected.
507 char frag_msg[512];
508 snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
junyulaic4e591a2018-11-26 22:36:10 +0900509 check_translated_packet(original[i], original_lengths[i], expected[i], expected_lengths[i],
510 frag_msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900511 }
512
513 // Sanity check that reassembling the original and translated fragments produces valid packets.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800514 uint8_t reassembled[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900515 size_t reassembled_len = sizeof(reassembled);
516 reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
517 check_packet(reassembled, reassembled_len, msg);
518
Brian Carlstromfcac4102014-02-24 20:03:01 -0800519 uint8_t translated[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900520 size_t translated_len = sizeof(translated);
521 do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
522 check_packet(translated, translated_len, msg);
523}
524
Lorenzo Colitti98089522014-10-09 22:29:45 +0900525int get_transport_checksum(const uint8_t *packet) {
526 struct iphdr *ip;
527 struct ip6_hdr *ip6;
528 uint8_t protocol;
529 const void *payload;
530
531 int version = ip_version(packet);
532 switch (version) {
533 case 4:
junyulaic4e591a2018-11-26 22:36:10 +0900534 ip = (struct iphdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900535 if (is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900536 return -1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900537 }
538 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900539 payload = ip + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900540 break;
541 case 6:
junyulaic4e591a2018-11-26 22:36:10 +0900542 ip6 = (struct ip6_hdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900543 protocol = ip6->ip6_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900544 payload = ip6 + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900545 break;
546 default:
547 return -1;
548 }
549
550 switch (protocol) {
551 case IPPROTO_UDP:
junyulaic4e591a2018-11-26 22:36:10 +0900552 return ((struct udphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900553
554 case IPPROTO_TCP:
junyulaic4e591a2018-11-26 22:36:10 +0900555 return ((struct tcphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900556
557 case IPPROTO_FRAGMENT:
558 default:
559 return -1;
560 }
561}
562
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900563static tun_data makeTunData() {
564 // Create some fake but realistic-looking sockets so update_clat_ipv6_address doesn't balk.
565 return {
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900566 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
Nick Desaulniers75f4dc62019-11-19 09:37:42 -0800567 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900568 .fd4 = socket(AF_UNIX, SOCK_DGRAM, 0),
569 };
570}
571
572void freeTunData(tun_data *tunnel) {
573 close(tunnel->write_fd6);
574 close(tunnel->read_fd6);
575 close(tunnel->fd4);
576}
577
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900578struct clat_config Global_Clatd_Config;
579
580class ClatdTest : public ::testing::Test {
581 protected:
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900582 static TunInterface sTun;
583
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900584 virtual void SetUp() {
585 inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
586 inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900587 memset(&Global_Clatd_Config.ipv6_local_subnet, 0, sizeof(in6_addr));
junyulaic4e591a2018-11-26 22:36:10 +0900588 Global_Clatd_Config.ipv6_host_id = in6addr_any;
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800589 Global_Clatd_Config.use_dynamic_iid = 1;
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900590 Global_Clatd_Config.default_pdp_interface = const_cast<char *>(sTun.name().c_str());
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900591 }
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900592
593 // Static because setting up the tun interface takes about 40ms.
594 static void SetUpTestCase() { ASSERT_EQ(0, sTun.init()); }
595
596 // Closing the socket removes the interface and IP addresses.
597 static void TearDownTestCase() { sTun.destroy(); }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900598};
599
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900600TunInterface ClatdTest::sTun;
601
Lorenzo Colitti98089522014-10-09 22:29:45 +0900602void expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
603 if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
604 char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
605 inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
606 inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
607 FAIL()
608 << "Unexpected IPv6 address:: "
609 << "\n Expected: " << expected_str
610 << "\n Actual: " << actual_str
611 << "\n";
612 }
613}
614
615TEST_F(ClatdTest, TestIPv6PrefixEqual) {
616 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
617 &Global_Clatd_Config.plat_subnet));
618 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
619 &Global_Clatd_Config.ipv6_local_subnet));
620
621 struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
622 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
623 EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
624
625 subnet2.s6_addr[6] = 0xff;
626 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
627 EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
628}
629
630int count_onebits(const void *data, size_t size) {
631 int onebits = 0;
632 for (size_t pos = 0; pos < size; pos++) {
junyulaic4e591a2018-11-26 22:36:10 +0900633 uint8_t *byte = ((uint8_t *)data) + pos;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900634 for (int shift = 0; shift < 8; shift++) {
635 onebits += (*byte >> shift) & 1;
636 }
637 }
638 return onebits;
639}
640
641TEST_F(ClatdTest, TestCountOnebits) {
642 uint64_t i;
643 i = 1;
644 ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
645 i <<= 61;
646 ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
junyulaic4e591a2018-11-26 22:36:10 +0900647 i |= ((uint64_t)1 << 33);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900648 ASSERT_EQ(2, count_onebits(&i, sizeof(i)));
649 i = 0xf1000202020000f0;
650 ASSERT_EQ(5 + 1 + 1 + 1 + 4, count_onebits(&i, sizeof(i)));
651}
652
653TEST_F(ClatdTest, TestGenIIDConfigured) {
654 struct in6_addr myaddr, expected;
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800655 Global_Clatd_Config.use_dynamic_iid = 0;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900656 ASSERT_TRUE(inet_pton(AF_INET6, "::bad:ace:d00d", &Global_Clatd_Config.ipv6_host_id));
657 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:0:bad:ace:d00d", &expected));
658 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &myaddr));
659 config_generate_local_ipv6_subnet(&myaddr);
660 expect_ipv6_addr_equal(&expected, &myaddr);
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800661
662 Global_Clatd_Config.use_dynamic_iid = 1;
663 config_generate_local_ipv6_subnet(&myaddr);
664 EXPECT_FALSE(IN6_ARE_ADDR_EQUAL(&expected, &myaddr));
Lorenzo Colitti98089522014-10-09 22:29:45 +0900665}
666
667TEST_F(ClatdTest, TestGenIIDRandom) {
668 struct in6_addr interface_ipv6;
669 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &interface_ipv6));
670 Global_Clatd_Config.ipv6_host_id = in6addr_any;
671
672 // Generate a boatload of random IIDs.
junyulaic4e591a2018-11-26 22:36:10 +0900673 int onebits = 0;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900674 uint64_t prev_iid = 0;
675 for (int i = 0; i < 100000; i++) {
junyulaic4e591a2018-11-26 22:36:10 +0900676 struct in6_addr myaddr = interface_ipv6;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900677
678 config_generate_local_ipv6_subnet(&myaddr);
679
680 // Check the generated IP address is in the same prefix as the interface IPv6 address.
681 EXPECT_TRUE(ipv6_prefix_equal(&interface_ipv6, &myaddr));
682
683 // Check that consecutive IIDs are not the same.
junyulaic4e591a2018-11-26 22:36:10 +0900684 uint64_t iid = *(uint64_t *)(&myaddr.s6_addr[8]);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900685 ASSERT_TRUE(iid != prev_iid)
686 << "Two consecutive random IIDs are the same: "
687 << std::showbase << std::hex
688 << iid << "\n";
689 prev_iid = iid;
690
691 // Check that the IID is checksum-neutral with the NAT64 prefix and the
692 // local prefix.
junyulaic4e591a2018-11-26 22:36:10 +0900693 struct in_addr *ipv4addr = &Global_Clatd_Config.ipv4_local_subnet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900694 struct in6_addr *plat_subnet = &Global_Clatd_Config.plat_subnet;
695
696 uint16_t c1 = ip_checksum_finish(ip_checksum_add(0, ipv4addr, sizeof(*ipv4addr)));
697 uint16_t c2 = ip_checksum_finish(ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
698 ip_checksum_add(0, &myaddr, sizeof(myaddr)));
699
700 if (c1 != c2) {
701 char myaddr_str[INET6_ADDRSTRLEN], plat_str[INET6_ADDRSTRLEN], ipv4_str[INET6_ADDRSTRLEN];
702 inet_ntop(AF_INET6, &myaddr, myaddr_str, sizeof(myaddr_str));
703 inet_ntop(AF_INET6, plat_subnet, plat_str, sizeof(plat_str));
704 inet_ntop(AF_INET, ipv4addr, ipv4_str, sizeof(ipv4_str));
705 FAIL()
706 << "Bad IID: " << myaddr_str
707 << " not checksum-neutral with " << ipv4_str << " and " << plat_str
708 << std::showbase << std::hex
709 << "\n IPv4 checksum: " << c1
710 << "\n IPv6 checksum: " << c2
711 << "\n";
712 }
713
714 // Check that IIDs are roughly random and use all the bits by counting the
715 // total number of bits set to 1 in a random sample of 100000 generated IIDs.
716 onebits += count_onebits(&iid, sizeof(iid));
717 }
718 EXPECT_LE(3190000, onebits);
719 EXPECT_GE(3210000, onebits);
720}
721
Lorenzo Colitti798f9932014-10-31 21:54:33 +0900722extern "C" addr_free_func config_is_ipv4_address_free;
723int never_free(in_addr_t /* addr */) { return 0; }
724int always_free(in_addr_t /* addr */) { return 1; }
725int only2_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 2; }
726int over6_free(in_addr_t addr) { return (ntohl(addr) & 0xff) >= 6; }
727int only10_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; }
728
729TEST_F(ClatdTest, SelectIPv4Address) {
730 struct in_addr addr;
731
732 inet_pton(AF_INET, kIPv4LocalAddr, &addr);
733
734 addr_free_func orig_config_is_ipv4_address_free = config_is_ipv4_address_free;
735
736 // If no addresses are free, return INADDR_NONE.
737 config_is_ipv4_address_free = never_free;
738 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
739 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 16));
740
741 // If the configured address is free, pick that. But a prefix that's too big is invalid.
742 config_is_ipv4_address_free = always_free;
743 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 29));
744 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 20));
745 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 15));
746
747 // A prefix length of 32 works, but anything above it is invalid.
748 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 32));
749 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 33));
750
751 // If another address is free, pick it.
752 config_is_ipv4_address_free = over6_free;
753 EXPECT_EQ(inet_addr("192.0.0.6"), config_select_ipv4_address(&addr, 29));
754
755 // Check that we wrap around to addresses that are lower than the first address.
756 config_is_ipv4_address_free = only2_free;
757 EXPECT_EQ(inet_addr("192.0.0.2"), config_select_ipv4_address(&addr, 29));
758 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 30));
759
760 // If a free address exists outside the prefix, we don't pick it.
761 config_is_ipv4_address_free = only10_free;
762 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
763 EXPECT_EQ(inet_addr("192.0.0.10"), config_select_ipv4_address(&addr, 24));
764
765 // Now try using the real function which sees if IP addresses are free using bind().
766 // Assume that the machine running the test has the address 127.0.0.1, but not 8.8.8.8.
767 config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
junyulaic4e591a2018-11-26 22:36:10 +0900768 addr.s_addr = inet_addr("8.8.8.8");
Lorenzo Colitti798f9932014-10-31 21:54:33 +0900769 EXPECT_EQ(inet_addr("8.8.8.8"), config_select_ipv4_address(&addr, 29));
770
771 addr.s_addr = inet_addr("127.0.0.1");
772 EXPECT_EQ(inet_addr("127.0.0.2"), config_select_ipv4_address(&addr, 29));
773}
774
Maciej Żenczykowskib00113f2020-01-18 23:56:14 -0800775TEST_F(ClatdTest, DetectMtu) {
776 // ::1 with bottom 32 bits set to 1 is still ::1 which routes via lo with mtu of 64KiB
777 ASSERT_EQ(detect_mtu(&in6addr_loopback, htonl(1), 0 /*MARK_UNSET*/), 65536);
778}
779
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900780TEST_F(ClatdTest, ConfigureTunIp) {
781 addr_free_func orig_config_is_ipv4_address_free = config_is_ipv4_address_free;
782 config_is_ipv4_address_free = over6_free;
783
784 Global_Clatd_Config.ipv4_local_prefixlen = 29;
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900785
786 // Create an interface for configure_tun_ip to configure and bring up.
787 TunInterface v4Iface;
788 ASSERT_EQ(0, v4Iface.init());
789 struct tun_data tunnel = makeTunData();
790 strlcpy(tunnel.device4, v4Iface.name().c_str(), sizeof(tunnel.device4));
791
Maciej Żenczykowskib00113f2020-01-18 23:56:14 -0800792 configure_tun_ip(&tunnel, nullptr /* v4_addr */, 1472);
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900793 EXPECT_EQ(inet_addr("192.0.0.6"), Global_Clatd_Config.ipv4_local_subnet.s_addr);
794
795 union anyip *ip = getinterface_ip(v4Iface.name().c_str(), AF_INET);
796 EXPECT_EQ(inet_addr("192.0.0.6"), ip->ip4.s_addr);
797 free(ip);
798
799 config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
800 v4Iface.destroy();
801}
802
803TEST_F(ClatdTest, ConfigureTunIpManual) {
804 addr_free_func orig_config_is_ipv4_address_free = config_is_ipv4_address_free;
805 config_is_ipv4_address_free = over6_free;
806
807 Global_Clatd_Config.ipv4_local_prefixlen = 29;
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900808
809 // Create an interface for configure_tun_ip to configure and bring up.
810 TunInterface v4Iface;
811 ASSERT_EQ(0, v4Iface.init());
812 struct tun_data tunnel = makeTunData();
813 strlcpy(tunnel.device4, v4Iface.name().c_str(), sizeof(tunnel.device4));
814
Maciej Żenczykowskib00113f2020-01-18 23:56:14 -0800815 configure_tun_ip(&tunnel, "192.0.2.1" /* v4_addr */, 1472);
Lorenzo Colittif0fac862019-01-11 18:10:11 +0900816 EXPECT_EQ(inet_addr("192.0.2.1"), Global_Clatd_Config.ipv4_local_subnet.s_addr);
817
818 union anyip *ip = getinterface_ip(v4Iface.name().c_str(), AF_INET);
819 ASSERT_NE(nullptr, ip);
820 EXPECT_EQ(inet_addr("192.0.2.1"), ip->ip4.s_addr);
821 free(ip);
822
823 config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
824 v4Iface.destroy();
825}
826
Lorenzo Colitti98089522014-10-09 22:29:45 +0900827TEST_F(ClatdTest, DataSanitycheck) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900828 // Sanity checks the data.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800829 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900830 ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
831
Brian Carlstromfcac4102014-02-24 20:03:01 -0800832 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900833 ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
834
Brian Carlstromfcac4102014-02-24 20:03:01 -0800835 uint8_t udp_header[] = { UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900836 ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
837
838 // Sanity checks check_packet.
839 struct udphdr *udp;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800840 uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900841 udp = (struct udphdr *)(v4_udp_packet + sizeof(struct iphdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900842 fix_udp_checksum(v4_udp_packet);
843 ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
844 check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
845
Brian Carlstromfcac4102014-02-24 20:03:01 -0800846 uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900847 udp = (struct udphdr *)(v6_udp_packet + sizeof(struct ip6_hdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900848 fix_udp_checksum(v6_udp_packet);
849 ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
850 check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
851
Brian Carlstromfcac4102014-02-24 20:03:01 -0800852 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900853 check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
854
Brian Carlstromfcac4102014-02-24 20:03:01 -0800855 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900856 check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
857
858 // Sanity checks reassemble_packet.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800859 uint8_t reassembled[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900860 size_t total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900861 reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), reassembled,
862 &total_length, "Reassembly sanity check");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900863 check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
864 ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
junyulaic4e591a2018-11-26 22:36:10 +0900865 ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *)reassembled))
866 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900867 check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
868
869 total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900870 reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments), reassembled,
871 &total_length, "IPv6 reassembly sanity check");
872 ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *)reassembled, total_length))
873 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900874 check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
875}
876
877TEST_F(ClatdTest, PseudoChecksum) {
878 uint32_t pseudo_checksum;
879
junyulaic4e591a2018-11-26 22:36:10 +0900880 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800881 uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900882 pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *)v4_header, UDP_LEN);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900883 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
884 ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900885 << "ipv4_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900886
junyulaic4e591a2018-11-26 22:36:10 +0900887 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800888 uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900889 pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *)v6_header, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900890 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
891 ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900892 << "ipv6_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900893}
894
895TEST_F(ClatdTest, TransportChecksum) {
junyulaic4e591a2018-11-26 22:36:10 +0900896 uint8_t udphdr[] = { UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800897 uint8_t payload[] = { PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900898 EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
junyulaic4e591a2018-11-26 22:36:10 +0900899 << "UDP partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900900 EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
junyulaic4e591a2018-11-26 22:36:10 +0900901 << "Payload partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900902
junyulaic4e591a2018-11-26 22:36:10 +0900903 uint8_t ip[] = { IPV4_UDP_HEADER };
904 uint8_t ip6[] = { IPV6_UDP_HEADER };
905 uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *)ip, UDP_LEN);
906 uint32_t ipv6_pseudo_sum =
907 ipv6_pseudo_header_checksum((struct ip6_hdr *)ip6, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900908
Maciej Żenczykowskif037e772019-11-10 23:02:13 -0800909 EXPECT_NE(0, ipv4_pseudo_sum);
910 EXPECT_NE(0, ipv6_pseudo_sum);
911 EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum % 0xFFFF) << "IPv4 pseudo-checksum sanity check\n";
912 EXPECT_EQ(0x644dU, ipv6_pseudo_sum % 0xFFFF) << "IPv6 pseudo-checksum sanity check\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900913 EXPECT_EQ(
914 kUdpV4Checksum,
915 ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
916 << "Unexpected UDP/IPv4 checksum\n";
917 EXPECT_EQ(
918 kUdpV6Checksum,
919 ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
920 << "Unexpected UDP/IPv6 checksum\n";
921
922 EXPECT_EQ(kUdpV6Checksum,
923 ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
924 << "Adjust IPv4/UDP checksum to IPv6\n";
925 EXPECT_EQ(kUdpV4Checksum,
926 ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
927 << "Adjust IPv6/UDP checksum to IPv4\n";
928}
929
930TEST_F(ClatdTest, AdjustChecksum) {
931 struct checksum_data {
932 uint16_t checksum;
933 uint32_t old_hdr_sum;
934 uint32_t new_hdr_sum;
935 uint16_t result;
936 } DATA[] = {
937 { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
938 { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
939 { 0xdd2f, 0x5555, 0x3285, 0x0000 },
940 { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
941 { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
942 };
Chih-Hung Hsieh05ff5082014-08-26 10:46:26 -0700943 unsigned i = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900944
945 for (i = 0; i < ARRAYSIZE(DATA); i++) {
946 struct checksum_data *data = DATA + i;
947 uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
948 EXPECT_EQ(result, data->result)
949 << "Incorrect checksum" << std::showbase << std::hex
950 << "\n Expected: " << data->result
951 << "\n Actual: " << result
952 << "\n checksum=" << data->checksum
953 << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
954 }
955}
956
957TEST_F(ClatdTest, Translate) {
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900958 // This test uses hardcoded packets so the clatd address must be fixed.
959 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
960
Brian Carlstromfcac4102014-02-24 20:03:01 -0800961 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
962 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900963 fix_udp_checksum(udp_ipv4);
964 fix_udp_checksum(udp_ipv6);
965 check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
966 "UDP/IPv4 -> UDP/IPv6 translation");
967 check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
968 "UDP/IPv6 -> UDP/IPv4 translation");
969
Brian Carlstromfcac4102014-02-24 20:03:01 -0800970 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
971 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900972 check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
973 "ICMP->ICMPv6 translation");
974 check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
975 "ICMPv6->ICMP translation");
976}
977
978TEST_F(ClatdTest, Fragmentation) {
Lorenzo Colitti72f770c2019-01-04 15:00:28 +0900979 // This test uses hardcoded packets so the clatd address must be fixed.
980 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
981
junyulaic4e591a2018-11-26 22:36:10 +0900982 check_fragment_translation(kIPv4Fragments, kIPv4FragLengths, kIPv6Fragments, kIPv6FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900983 ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
984
junyulaic4e591a2018-11-26 22:36:10 +0900985 check_fragment_translation(kIPv6Fragments, kIPv6FragLengths, kIPv4Fragments, kIPv4FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900986 ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
987}
Lorenzo Colitti98089522014-10-09 22:29:45 +0900988
989void check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
990 size_t expected_len, const char *msg) {
991 uint8_t translated[MAXMTU];
992 size_t translated_len = sizeof(translated);
993 do_translate_packet(original, original_len, translated, &translated_len, msg);
994 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
995 // do_translate_packet already checks packets for validity and verifies the checksum.
junyulaic4e591a2018-11-26 22:36:10 +0900996 int original_check = get_transport_checksum(original);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900997 int translated_check = get_transport_checksum(translated);
998 ASSERT_NE(-1, original_check);
999 ASSERT_NE(-1, translated_check);
1000 ASSERT_EQ(original_check, translated_check)
junyulaic4e591a2018-11-26 22:36:10 +09001001 << "Not checksum neutral: original and translated checksums differ\n";
Lorenzo Colitti98089522014-10-09 22:29:45 +09001002}
1003
1004TEST_F(ClatdTest, TranslateChecksumNeutral) {
1005 // Generate a random clat IPv6 address and check that translation is checksum-neutral.
1006 Global_Clatd_Config.ipv6_host_id = in6addr_any;
1007 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
1008 &Global_Clatd_Config.ipv6_local_subnet));
1009 config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +09001010 ASSERT_NE(htonl((uint32_t)0x00000464), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
junyulaic4e591a2018-11-26 22:36:10 +09001011 ASSERT_NE((uint32_t)0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
Lorenzo Colitti98089522014-10-09 22:29:45 +09001012
1013 // Check that translating UDP packets is checksum-neutral. First, IPv4.
1014 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
1015 fix_udp_checksum(udp_ipv4);
1016 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
1017 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
1018
1019 // Now try IPv6.
1020 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
1021 // The test packet uses the static IID, not the random IID. Fix up the source address.
junyulaic4e591a2018-11-26 22:36:10 +09001022 struct ip6_hdr *ip6 = (struct ip6_hdr *)udp_ipv6;
Lorenzo Colitti98089522014-10-09 22:29:45 +09001023 memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
1024 fix_udp_checksum(udp_ipv6);
1025 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
1026 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
1027}
Lorenzo Colitti72f770c2019-01-04 15:00:28 +09001028
1029TEST_F(ClatdTest, GetInterfaceIp) {
1030 union anyip *ip = getinterface_ip(sTun.name().c_str(), AF_INET6);
1031 ASSERT_NE(nullptr, ip);
1032 in6_addr expected = sTun.srcAddr();
1033 in6_addr actual = ip->ip6;
1034 expect_ipv6_addr_equal(&expected, &actual);
1035}
1036
Lorenzo Colittif0fac862019-01-11 18:10:11 +09001037void expectSocketBound(int ifindex, int sock) {
1038 // Check that the packet socket is bound to the interface. We can't check the socket filter
1039 // because there is no way to fetch it from the kernel.
1040 sockaddr_ll sll;
1041 socklen_t len = sizeof(sll);
1042 ASSERT_EQ(0, getsockname(sock, reinterpret_cast<sockaddr *>(&sll), &len));
1043 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
1044 EXPECT_EQ(ifindex, sll.sll_ifindex);
1045}
1046
Lorenzo Colitti66deecd2019-01-04 12:27:27 +09001047TEST_F(ClatdTest, ConfigureIpv6Address) {
Lorenzo Colittif0fac862019-01-11 18:10:11 +09001048 struct tun_data tunnel = makeTunData();
Lorenzo Colitti72f770c2019-01-04 15:00:28 +09001049
Lorenzo Colittif0fac862019-01-11 18:10:11 +09001050 ASSERT_TRUE(IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_local_subnet));
1051
1052 const char *addrStr = "2001:db8::f00";
1053 in6_addr addr;
1054 ASSERT_EQ(1, inet_pton(AF_INET6, addrStr, &addr));
1055 ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, sTun.name().c_str(), addrStr));
1056
1057 EXPECT_EQ(htonl(0x20010db8), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[0]);
1058 EXPECT_EQ(htonl(0x00000000), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[1]);
1059 EXPECT_EQ(htonl(0x00000000), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[2]);
1060 EXPECT_EQ(htonl(0x00000f00), Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
1061
Lorenzo Colitti72f770c2019-01-04 15:00:28 +09001062 // Check that the packet socket is bound to the interface. We can't check the socket filter
1063 // because there is no way to fetch it from the kernel.
1064 sockaddr_ll sll;
1065 socklen_t len = sizeof(sll);
1066 ASSERT_EQ(0, getsockname(tunnel.read_fd6, reinterpret_cast<sockaddr *>(&sll), &len));
1067 EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
1068 EXPECT_EQ(sll.sll_ifindex, sTun.ifindex());
Lorenzo Colittif0fac862019-01-11 18:10:11 +09001069
1070 expectSocketBound(sTun.ifindex(), tunnel.read_fd6);
1071
1072 freeTunData(&tunnel);
Lorenzo Colitti72f770c2019-01-04 15:00:28 +09001073}
Lorenzo Colitti66deecd2019-01-04 12:27:27 +09001074
1075TEST_F(ClatdTest, Ipv6AddressChanged) {
1076 // Configure the clat IPv6 address.
1077 struct tun_data tunnel = {
Lorenzo Colitti66deecd2019-01-04 12:27:27 +09001078 .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
Nick Desaulniers75f4dc62019-11-19 09:37:42 -08001079 .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
Lorenzo Colitti66deecd2019-01-04 12:27:27 +09001080 };
1081 const char *ifname = sTun.name().c_str();
Lorenzo Colittif0fac862019-01-11 18:10:11 +09001082 ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, ifname, nullptr));
Lorenzo Colitti66deecd2019-01-04 12:27:27 +09001083 EXPECT_EQ(0, ipv6_address_changed(ifname));
1084 EXPECT_EQ(0, ipv6_address_changed(ifname));
1085
1086 // Change the IP address on the tun interface to a new prefix.
1087 char srcaddr[INET6_ADDRSTRLEN];
1088 char dstaddr[INET6_ADDRSTRLEN];
1089 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.srcAddr(), srcaddr, sizeof(srcaddr)));
1090 ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.dstAddr(), dstaddr, sizeof(dstaddr)));
1091 EXPECT_EQ(0, ifc_del_address(ifname, srcaddr, 64));
1092 EXPECT_EQ(0, ifc_del_address(ifname, dstaddr, 64));
1093
1094 // Check that we can tell that the address has changed.
1095 EXPECT_EQ(0, ifc_add_address(ifname, "2001:db8::1:2", 64));
1096 EXPECT_EQ(1, ipv6_address_changed(ifname));
1097 EXPECT_EQ(1, ipv6_address_changed(ifname));
1098
1099 // Restore the tun interface configuration.
1100 sTun.destroy();
1101 ASSERT_EQ(0, sTun.init());
1102}