blob: 2a10101f89382cd0ff4ba394a28939868e5c0d50 [file] [log] [blame]
Lorenzo Colittif3beefc2014-02-14 13:19:27 +09001/*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * clatd_test.cpp - unit tests for clatd
17 */
18
19#include <iostream>
20
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090021#include <arpa/inet.h>
Lorenzo Colitti98089522014-10-09 22:29:45 +090022#include <netinet/in6.h>
junyulaic4e591a2018-11-26 22:36:10 +090023#include <stdio.h>
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090024#include <sys/uio.h>
25
26#include <gtest/gtest.h>
27
28extern "C" {
29#include "checksum.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090030#include "clatd.h"
junyulaic4e591a2018-11-26 22:36:10 +090031#include "config.h"
32#include "translate.h"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090033}
34
35// For convenience.
36#define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0])
37
38// Default translation parameters.
junyulaic4e591a2018-11-26 22:36:10 +090039static const char kIPv4LocalAddr[] = "192.0.0.4";
40static const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090041static const char kIPv6PlatSubnet[] = "64:ff9b::";
42
junyulaic4e591a2018-11-26 22:36:10 +090043// clang-format off
Lorenzo Colittif3beefc2014-02-14 13:19:27 +090044// Test packet portions. Defined as macros because it's easy to concatenate them to make packets.
45#define IPV4_HEADER(p, c1, c2) \
46 0x45, 0x00, 0, 41, /* Version=4, IHL=5, ToS=0x80, len=41 */ \
47 0x00, 0x00, 0x40, 0x00, /* ID=0x0000, flags=IP_DF, offset=0 */ \
48 55, (p), (c1), (c2), /* TTL=55, protocol=p, checksum=c1,c2 */ \
49 192, 0, 0, 4, /* Src=192.0.0.4 */ \
50 8, 8, 8, 8, /* Dst=8.8.8.8 */
51#define IPV4_UDP_HEADER IPV4_HEADER(IPPROTO_UDP, 0x73, 0xb0)
52#define IPV4_ICMP_HEADER IPV4_HEADER(IPPROTO_ICMP, 0x73, 0xc0)
53
54#define IPV6_HEADER(p) \
55 0x60, 0x00, 0, 0, /* Version=6, tclass=0x00, flowlabel=0 */ \
56 0, 21, (p), 55, /* plen=11, nxthdr=p, hlim=55 */ \
57 0x20, 0x01, 0x0d, 0xb8, /* Src=2001:db8:0:b11::464 */ \
58 0x00, 0x00, 0x0b, 0x11, \
59 0x00, 0x00, 0x00, 0x00, \
60 0x00, 0x00, 0x04, 0x64, \
61 0x00, 0x64, 0xff, 0x9b, /* Dst=64:ff9b::8.8.8.8 */ \
62 0x00, 0x00, 0x00, 0x00, \
63 0x00, 0x00, 0x00, 0x00, \
64 0x08, 0x08, 0x08, 0x08,
65#define IPV6_UDP_HEADER IPV6_HEADER(IPPROTO_UDP)
66#define IPV6_ICMPV6_HEADER IPV6_HEADER(IPPROTO_ICMPV6)
67
68#define UDP_LEN 21
69#define UDP_HEADER \
70 0xc8, 0x8b, 0, 53, /* Port 51339->53 */ \
71 0x00, UDP_LEN, 0, 0, /* Length 21, checksum empty for now */
72
73#define PAYLOAD 'H', 'e', 'l', 'l', 'o', ' ', 0x4e, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0x00
74
75#define IPV4_PING \
76 0x08, 0x00, 0x88, 0xd0, /* Type 8, code 0, checksum 0x88d0 */ \
77 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
78
79#define IPV6_PING \
80 0x80, 0x00, 0xc3, 0x42, /* Type 128, code 0, checksum 0xc342 */ \
81 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */
82
83// Macros to return pseudo-headers from packets.
84#define IPV4_PSEUDOHEADER(ip, tlen) \
85 ip[12], ip[13], ip[14], ip[15], /* Source address */ \
86 ip[16], ip[17], ip[18], ip[19], /* Destination address */ \
87 0, ip[9], /* 0, protocol */ \
88 ((tlen) >> 16) & 0xff, (tlen) & 0xff, /* Transport length */
89
90#define IPV6_PSEUDOHEADER(ip6, protocol, tlen) \
91 ip6[8], ip6[9], ip6[10], ip6[11], /* Source address */ \
92 ip6[12], ip6[13], ip6[14], ip6[15], \
93 ip6[16], ip6[17], ip6[18], ip6[19], \
94 ip6[20], ip6[21], ip6[22], ip6[23], \
95 ip6[24], ip6[25], ip6[26], ip6[27], /* Destination address */ \
96 ip6[28], ip6[29], ip6[30], ip6[31], \
97 ip6[32], ip6[33], ip6[34], ip6[35], \
98 ip6[36], ip6[37], ip6[38], ip6[39], \
99 ((tlen) >> 24) & 0xff, /* Transport length */ \
100 ((tlen) >> 16) & 0xff, \
101 ((tlen) >> 8) & 0xff, \
102 (tlen) & 0xff, \
103 0, 0, 0, (protocol),
104
105// A fragmented DNS request.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800106static const uint8_t kIPv4Frag1[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900107 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x00, 0x40, 0x11,
108 0x8c, 0x6d, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
109 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
110 0x01, 0x00, 0x00, 0x01, 0x00, 0x00
111};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800112static const uint8_t kIPv4Frag2[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900113 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x02, 0x40, 0x11,
114 0x8c, 0x6b, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
115 0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06,
116 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65
117};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800118static const uint8_t kIPv4Frag3[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900119 0x45, 0x00, 0x00, 0x1d, 0xfe, 0x47, 0x00, 0x04, 0x40, 0x11,
120 0xac, 0x70, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
121 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
122};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800123static const uint8_t *kIPv4Fragments[] = { kIPv4Frag1, kIPv4Frag2, kIPv4Frag3 };
124static const size_t kIPv4FragLengths[] = { sizeof(kIPv4Frag1), sizeof(kIPv4Frag2),
125 sizeof(kIPv4Frag3) };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900126
Brian Carlstromfcac4102014-02-24 20:03:01 -0800127static const uint8_t kIPv6Frag1[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900128 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
129 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
132 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x47, 0x14, 0x5d,
133 0x00, 0x35, 0x00, 0x29, 0xeb, 0x91, 0x50, 0x47, 0x01, 0x00,
134 0x00, 0x01, 0x00, 0x00
135};
136
Brian Carlstromfcac4102014-02-24 20:03:01 -0800137static const uint8_t kIPv6Frag2[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900138 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
139 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
142 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0xfe, 0x47, 0x00, 0x00,
143 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f,
144 0x6f, 0x67, 0x6c, 0x65
145};
146
Brian Carlstromfcac4102014-02-24 20:03:01 -0800147static const uint8_t kIPv6Frag3[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900148 0x60, 0x00, 0x00, 0x00, 0x00, 0x11, 0x2c, 0x40, 0x20, 0x01,
149 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
152 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0xfe, 0x47, 0x03, 0x63,
153 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
154};
Brian Carlstromfcac4102014-02-24 20:03:01 -0800155static const uint8_t *kIPv6Fragments[] = { kIPv6Frag1, kIPv6Frag2, kIPv6Frag3 };
156static const size_t kIPv6FragLengths[] = { sizeof(kIPv6Frag1), sizeof(kIPv6Frag2),
157 sizeof(kIPv6Frag3) };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900158
Brian Carlstromfcac4102014-02-24 20:03:01 -0800159static const uint8_t kReassembledIPv4[] = {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900160 0x45, 0x00, 0x00, 0x3d, 0xfe, 0x47, 0x00, 0x00, 0x40, 0x11,
161 0xac, 0x54, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
162 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
163 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67,
165 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
166 0x01
167};
junyulaic4e591a2018-11-26 22:36:10 +0900168// clang-format on
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900169
170// Expected checksums.
171static const uint32_t kUdpPartialChecksum = 0xd5c8;
172static const uint32_t kPayloadPartialChecksum = 0x31e9c;
173static const uint16_t kUdpV4Checksum = 0xd0c7;
174static const uint16_t kUdpV6Checksum = 0xa74a;
175
Brian Carlstromfcac4102014-02-24 20:03:01 -0800176uint8_t ip_version(const uint8_t *packet) {
177 uint8_t version = packet[0] >> 4;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900178 return version;
179}
180
181int is_ipv4_fragment(struct iphdr *ip) {
182 // A packet is a fragment if its fragment offset is nonzero or if the MF flag is set.
183 return ntohs(ip->frag_off) & (IP_OFFMASK | IP_MF);
184}
185
186int is_ipv6_fragment(struct ip6_hdr *ip6, size_t len) {
187 if (ip6->ip6_nxt != IPPROTO_FRAGMENT) {
188 return 0;
189 }
junyulaic4e591a2018-11-26 22:36:10 +0900190 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900191 return len >= sizeof(*ip6) + sizeof(*frag) &&
junyulaic4e591a2018-11-26 22:36:10 +0900192 (frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900193}
194
195int ipv4_fragment_offset(struct iphdr *ip) {
196 return ntohs(ip->frag_off) & IP_OFFMASK;
197}
198
199int ipv6_fragment_offset(struct ip6_frag *frag) {
200 return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3);
201}
202
Brian Carlstromfcac4102014-02-24 20:03:01 -0800203void check_packet(const uint8_t *packet, size_t len, const char *msg) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900204 void *payload;
junyulaic4e591a2018-11-26 22:36:10 +0900205 size_t payload_length = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900206 uint32_t pseudo_checksum = 0;
junyulaic4e591a2018-11-26 22:36:10 +0900207 uint8_t protocol = 0;
208 int version = ip_version(packet);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900209 switch (version) {
210 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900211 struct iphdr *ip = (struct iphdr *)packet;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900212 ASSERT_GE(len, sizeof(*ip)) << msg << ": IPv4 packet shorter than IPv4 header\n";
213 EXPECT_EQ(5, ip->ihl) << msg << ": Unsupported IP header length\n";
214 EXPECT_EQ(len, ntohs(ip->tot_len)) << msg << ": Incorrect IPv4 length\n";
215 EXPECT_EQ(0, ip_checksum(ip, sizeof(*ip))) << msg << ": Incorrect IP checksum\n";
216 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900217 payload = ip + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900218 if (!is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900219 payload_length = len - sizeof(*ip);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900220 pseudo_checksum = ipv4_pseudo_header_checksum(ip, payload_length);
221 }
222 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP)
junyulaic4e591a2018-11-26 22:36:10 +0900223 << msg << ": Unsupported IPv4 protocol " << protocol << "\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900224 break;
225 }
226 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900227 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900228 ASSERT_GE(len, sizeof(*ip6)) << msg << ": IPv6 packet shorter than IPv6 header\n";
229 EXPECT_EQ(len - sizeof(*ip6), htons(ip6->ip6_plen)) << msg << ": Incorrect IPv6 length\n";
230
231 if (ip6->ip6_nxt == IPPROTO_FRAGMENT) {
junyulaic4e591a2018-11-26 22:36:10 +0900232 struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900233 ASSERT_GE(len, sizeof(*ip6) + sizeof(*frag))
junyulaic4e591a2018-11-26 22:36:10 +0900234 << msg << ": IPv6 fragment: short fragment header\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900235 protocol = frag->ip6f_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900236 payload = frag + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900237 // Even though the packet has a Fragment header, it might not be a fragment.
238 if (!is_ipv6_fragment(ip6, len)) {
239 payload_length = len - sizeof(*ip6) - sizeof(*frag);
240 }
241 } else {
242 // Since there are no extension headers except Fragment, this must be the payload.
junyulaic4e591a2018-11-26 22:36:10 +0900243 protocol = ip6->ip6_nxt;
244 payload = ip6 + 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900245 payload_length = len - sizeof(*ip6);
246 }
247 ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMPV6)
junyulaic4e591a2018-11-26 22:36:10 +0900248 << msg << ": Unsupported IPv6 next header " << protocol;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900249 if (payload_length) {
250 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, payload_length, protocol);
251 }
252 break;
253 }
254 default:
255 FAIL() << msg << ": Unsupported IP version " << version << "\n";
256 return;
257 }
258
259 // If we understand the payload, verify the checksum.
260 if (payload_length) {
261 uint16_t checksum;
junyulaic4e591a2018-11-26 22:36:10 +0900262 switch (protocol) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900263 case IPPROTO_UDP:
264 case IPPROTO_TCP:
265 case IPPROTO_ICMPV6:
266 checksum = ip_checksum_finish(ip_checksum_add(pseudo_checksum, payload, payload_length));
267 break;
268 case IPPROTO_ICMP:
269 checksum = ip_checksum(payload, payload_length);
270 break;
271 default:
272 checksum = 0; // Don't check.
273 break;
274 }
275 EXPECT_EQ(0, checksum) << msg << ": Incorrect transport checksum\n";
276 }
277
278 if (protocol == IPPROTO_UDP) {
junyulaic4e591a2018-11-26 22:36:10 +0900279 struct udphdr *udp = (struct udphdr *)payload;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900280 EXPECT_NE(0, udp->check) << msg << ": UDP checksum 0 should be 0xffff";
281 // If this is not a fragment, check the UDP length field.
282 if (payload_length) {
283 EXPECT_EQ(payload_length, ntohs(udp->len)) << msg << ": Incorrect UDP length\n";
284 }
285 }
286}
287
Brian Carlstromfcac4102014-02-24 20:03:01 -0800288void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int numpackets,
289 uint8_t *reassembled, size_t *reassembled_len, const char *msg) {
junyulaic4e591a2018-11-26 22:36:10 +0900290 struct iphdr *ip = NULL;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900291 struct ip6_hdr *ip6 = NULL;
junyulaic4e591a2018-11-26 22:36:10 +0900292 size_t total_length, pos = 0;
Ben Cheng932614e2014-04-02 17:00:26 -0700293 uint8_t protocol = 0;
junyulaic4e591a2018-11-26 22:36:10 +0900294 uint8_t version = ip_version(fragments[0]);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900295
296 for (int i = 0; i < numpackets; i++) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800297 const uint8_t *packet = fragments[i];
junyulaic4e591a2018-11-26 22:36:10 +0900298 int len = lengths[i];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900299 int headersize, payload_offset;
300
301 ASSERT_EQ(ip_version(packet), version) << msg << ": Inconsistent fragment versions\n";
302 check_packet(packet, len, "Fragment sanity check");
303
304 switch (version) {
305 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900306 struct iphdr *ip_orig = (struct iphdr *)packet;
307 headersize = sizeof(*ip_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900308 ASSERT_TRUE(is_ipv4_fragment(ip_orig))
junyulaic4e591a2018-11-26 22:36:10 +0900309 << msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n";
310 ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip) : 0))
311 << msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900312
junyulaic4e591a2018-11-26 22:36:10 +0900313 headersize = sizeof(*ip_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900314 payload_offset = headersize;
315 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900316 ip = (struct iphdr *)reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900317 }
318 break;
319 }
320 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900321 struct ip6_hdr *ip6_orig = (struct ip6_hdr *)packet;
322 struct ip6_frag *frag = (struct ip6_frag *)(ip6_orig + 1);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900323 ASSERT_TRUE(is_ipv6_fragment(ip6_orig, len))
junyulaic4e591a2018-11-26 22:36:10 +0900324 << msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n";
325 ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6) : 0))
326 << msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900327
junyulaic4e591a2018-11-26 22:36:10 +0900328 headersize = sizeof(*ip6_orig);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900329 payload_offset = sizeof(*ip6_orig) + sizeof(*frag);
330 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900331 ip6 = (struct ip6_hdr *)reassembled;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900332 protocol = frag->ip6f_nxt;
333 }
334 break;
335 }
336 default:
337 FAIL() << msg << ": Invalid IP version << " << version;
338 }
339
340 // If this is the first fragment, copy the header.
341 if (pos == 0) {
junyulaic4e591a2018-11-26 22:36:10 +0900342 ASSERT_LT(headersize, (int)*reassembled_len) << msg << ": Reassembly buffer too small\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900343 memcpy(reassembled, packet, headersize);
344 total_length = headersize;
345 pos += headersize;
346 }
347
348 // Copy the payload.
349 int payload_length = len - payload_offset;
350 total_length += payload_length;
Ben Cheng932614e2014-04-02 17:00:26 -0700351 ASSERT_LT(total_length, *reassembled_len) << msg << ": Reassembly buffer too small\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900352 memcpy(reassembled + pos, packet + payload_offset, payload_length);
353 pos += payload_length;
354 }
355
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900356 // Fix up the reassembled headers to reflect fragmentation and length (and IPv4 checksum).
357 ASSERT_EQ(total_length, pos) << msg << ": Reassembled packet length incorrect\n";
358 if (ip) {
359 ip->frag_off &= ~htons(IP_MF);
360 ip->tot_len = htons(total_length);
junyulaic4e591a2018-11-26 22:36:10 +0900361 ip->check = 0;
362 ip->check = ip_checksum(ip, sizeof(*ip));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900363 ASSERT_FALSE(is_ipv4_fragment(ip)) << msg << ": reassembled IPv4 packet is a fragment!\n";
364 }
365 if (ip6) {
junyulaic4e591a2018-11-26 22:36:10 +0900366 ip6->ip6_nxt = protocol;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900367 ip6->ip6_plen = htons(total_length - sizeof(*ip6));
368 ASSERT_FALSE(is_ipv6_fragment(ip6, ip6->ip6_plen))
junyulaic4e591a2018-11-26 22:36:10 +0900369 << msg << ": reassembled IPv6 packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900370 }
371
372 *reassembled_len = total_length;
373}
374
Lorenzo Colitti98089522014-10-09 22:29:45 +0900375void check_data_matches(const void *expected, const void *actual, size_t len, const char *msg) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900376 if (memcmp(expected, actual, len)) {
377 // Hex dump, 20 bytes per line, one space between bytes (1 byte = 3 chars), indented by 4.
378 int hexdump_len = len * 3 + (len / 20 + 1) * 5;
379 char expected_hexdump[hexdump_len], actual_hexdump[hexdump_len];
380 unsigned pos = 0;
381 for (unsigned i = 0; i < len; i++) {
382 if (i % 20 == 0) {
George Burgess IV2dcca6f2016-02-24 15:55:54 -0800383 snprintf(expected_hexdump + pos, hexdump_len - pos, "\n ");
384 snprintf(actual_hexdump + pos, hexdump_len - pos, "\n ");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900385 pos += 4;
386 }
junyulaic4e591a2018-11-26 22:36:10 +0900387 snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)expected)[i]);
388 snprintf(actual_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)actual)[i]);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900389 pos += 3;
390 }
Lorenzo Colitti98089522014-10-09 22:29:45 +0900391 FAIL() << msg << ": Data doesn't match"
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900392 << "\n Expected:" << (char *) expected_hexdump
393 << "\n Actual:" << (char *) actual_hexdump << "\n";
394 }
395}
396
junyulaic4e591a2018-11-26 22:36:10 +0900397void fix_udp_checksum(uint8_t *packet) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900398 uint32_t pseudo_checksum;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800399 uint8_t version = ip_version(packet);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900400 struct udphdr *udp;
401 switch (version) {
402 case 4: {
junyulaic4e591a2018-11-26 22:36:10 +0900403 struct iphdr *ip = (struct iphdr *)packet;
404 udp = (struct udphdr *)(ip + 1);
405 pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900406 break;
407 }
408 case 6: {
junyulaic4e591a2018-11-26 22:36:10 +0900409 struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
410 udp = (struct udphdr *)(ip6 + 1);
411 pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900412 break;
413 }
414 default:
415 FAIL() << "unsupported IP version" << version << "\n";
416 return;
junyulaic4e591a2018-11-26 22:36:10 +0900417 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900418
419 udp->check = 0;
420 udp->check = ip_checksum_finish(ip_checksum_add(pseudo_checksum, udp, ntohs(udp->len)));
421}
422
Lorenzo Colittice140882014-06-02 21:20:40 +0900423// Testing stub for send_rawv6. The real version uses sendmsg() with a
424// destination IPv6 address, and attempting to call that on our test socketpair
425// fd results in EINVAL.
junyulaic4e591a2018-11-26 22:36:10 +0900426extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) { writev(fd, out, iov_len); }
Lorenzo Colittice140882014-06-02 21:20:40 +0900427
Brian Carlstromfcac4102014-02-24 20:03:01 -0800428void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *out, size_t *outlen,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900429 const char *msg) {
430 int fds[2];
431 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, fds)) {
432 abort();
433 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900434
435 char foo[512];
436 snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg);
437 check_packet(original, original_len, foo);
438
Lorenzo Colittie24982e2014-06-02 15:49:36 +0900439 int read_fd, write_fd;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900440 uint16_t expected_proto;
441 int version = ip_version(original);
442 switch (version) {
443 case 4:
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900444 expected_proto = htons(ETH_P_IPV6);
junyulaic4e591a2018-11-26 22:36:10 +0900445 read_fd = fds[1];
446 write_fd = fds[0];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900447 break;
448 case 6:
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900449 expected_proto = htons(ETH_P_IP);
junyulaic4e591a2018-11-26 22:36:10 +0900450 read_fd = fds[0];
451 write_fd = fds[1];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900452 break;
453 default:
454 FAIL() << msg << ": Unsupported IP version " << version << "\n";
455 break;
456 }
457
Lorenzo Colittie24982e2014-06-02 15:49:36 +0900458 translate_packet(write_fd, (version == 4), original, original_len);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900459
Lorenzo Colitti98089522014-10-09 22:29:45 +0900460 snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
Lorenzo Colittice140882014-06-02 21:20:40 +0900461 if (version == 6) {
462 // Translating to IPv4. Expect a tun header.
463 struct tun_pi new_tun_header;
464 struct iovec iov[] = {
465 { &new_tun_header, sizeof(new_tun_header) },
junyulaic4e591a2018-11-26 22:36:10 +0900466 { out, *outlen },
Lorenzo Colittice140882014-06-02 21:20:40 +0900467 };
junyulaic4e591a2018-11-26 22:36:10 +0900468
Lorenzo Colittice140882014-06-02 21:20:40 +0900469 int len = readv(read_fd, iov, 2);
junyulaic4e591a2018-11-26 22:36:10 +0900470 if (len > (int)sizeof(new_tun_header)) {
471 ASSERT_LT((size_t)len, *outlen) << msg << ": Translated packet buffer too small\n";
Lorenzo Colittice140882014-06-02 21:20:40 +0900472 EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
473 *outlen = len - sizeof(new_tun_header);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900474 check_packet(out, *outlen, msg);
Lorenzo Colittice140882014-06-02 21:20:40 +0900475 } else {
Lorenzo Colitti98089522014-10-09 22:29:45 +0900476 FAIL() << msg << ": Packet was not translated: len=" << len;
Lorenzo Colittice140882014-06-02 21:20:40 +0900477 *outlen = 0;
478 }
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900479 } else {
Lorenzo Colittice140882014-06-02 21:20:40 +0900480 // Translating to IPv6. Expect raw packet.
481 *outlen = read(read_fd, out, *outlen);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900482 check_packet(out, *outlen, msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900483 }
484}
485
junyulaic4e591a2018-11-26 22:36:10 +0900486void check_translated_packet(const uint8_t *original, size_t original_len, const uint8_t *expected,
487 size_t expected_len, const char *msg) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800488 uint8_t translated[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900489 size_t translated_len = sizeof(translated);
490 do_translate_packet(original, original_len, translated, &translated_len, msg);
491 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
492 check_data_matches(expected, translated, translated_len, msg);
493}
494
Brian Carlstromfcac4102014-02-24 20:03:01 -0800495void check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
496 const uint8_t *expected[], const size_t expected_lengths[],
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900497 int numfragments, const char *msg) {
498 for (int i = 0; i < numfragments; i++) {
499 // Check that each of the fragments translates as expected.
500 char frag_msg[512];
501 snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
junyulaic4e591a2018-11-26 22:36:10 +0900502 check_translated_packet(original[i], original_lengths[i], expected[i], expected_lengths[i],
503 frag_msg);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900504 }
505
506 // Sanity check that reassembling the original and translated fragments produces valid packets.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800507 uint8_t reassembled[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900508 size_t reassembled_len = sizeof(reassembled);
509 reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
510 check_packet(reassembled, reassembled_len, msg);
511
Brian Carlstromfcac4102014-02-24 20:03:01 -0800512 uint8_t translated[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900513 size_t translated_len = sizeof(translated);
514 do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
515 check_packet(translated, translated_len, msg);
516}
517
Lorenzo Colitti98089522014-10-09 22:29:45 +0900518int get_transport_checksum(const uint8_t *packet) {
519 struct iphdr *ip;
520 struct ip6_hdr *ip6;
521 uint8_t protocol;
522 const void *payload;
523
524 int version = ip_version(packet);
525 switch (version) {
526 case 4:
junyulaic4e591a2018-11-26 22:36:10 +0900527 ip = (struct iphdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900528 if (is_ipv4_fragment(ip)) {
junyulaic4e591a2018-11-26 22:36:10 +0900529 return -1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900530 }
531 protocol = ip->protocol;
junyulaic4e591a2018-11-26 22:36:10 +0900532 payload = ip + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900533 break;
534 case 6:
junyulaic4e591a2018-11-26 22:36:10 +0900535 ip6 = (struct ip6_hdr *)packet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900536 protocol = ip6->ip6_nxt;
junyulaic4e591a2018-11-26 22:36:10 +0900537 payload = ip6 + 1;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900538 break;
539 default:
540 return -1;
541 }
542
543 switch (protocol) {
544 case IPPROTO_UDP:
junyulaic4e591a2018-11-26 22:36:10 +0900545 return ((struct udphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900546
547 case IPPROTO_TCP:
junyulaic4e591a2018-11-26 22:36:10 +0900548 return ((struct tcphdr *)payload)->check;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900549
550 case IPPROTO_FRAGMENT:
551 default:
552 return -1;
553 }
554}
555
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900556struct clat_config Global_Clatd_Config;
557
558class ClatdTest : public ::testing::Test {
559 protected:
560 virtual void SetUp() {
561 inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
562 inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
563 inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
junyulaic4e591a2018-11-26 22:36:10 +0900564 Global_Clatd_Config.ipv6_host_id = in6addr_any;
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800565 Global_Clatd_Config.use_dynamic_iid = 1;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900566 }
567};
568
Lorenzo Colitti98089522014-10-09 22:29:45 +0900569void expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
570 if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
571 char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
572 inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
573 inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
574 FAIL()
575 << "Unexpected IPv6 address:: "
576 << "\n Expected: " << expected_str
577 << "\n Actual: " << actual_str
578 << "\n";
579 }
580}
581
582TEST_F(ClatdTest, TestIPv6PrefixEqual) {
583 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
584 &Global_Clatd_Config.plat_subnet));
585 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
586 &Global_Clatd_Config.ipv6_local_subnet));
587
588 struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
589 EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
590 EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
591
592 subnet2.s6_addr[6] = 0xff;
593 EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
594 EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
595}
596
597int count_onebits(const void *data, size_t size) {
598 int onebits = 0;
599 for (size_t pos = 0; pos < size; pos++) {
junyulaic4e591a2018-11-26 22:36:10 +0900600 uint8_t *byte = ((uint8_t *)data) + pos;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900601 for (int shift = 0; shift < 8; shift++) {
602 onebits += (*byte >> shift) & 1;
603 }
604 }
605 return onebits;
606}
607
608TEST_F(ClatdTest, TestCountOnebits) {
609 uint64_t i;
610 i = 1;
611 ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
612 i <<= 61;
613 ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
junyulaic4e591a2018-11-26 22:36:10 +0900614 i |= ((uint64_t)1 << 33);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900615 ASSERT_EQ(2, count_onebits(&i, sizeof(i)));
616 i = 0xf1000202020000f0;
617 ASSERT_EQ(5 + 1 + 1 + 1 + 4, count_onebits(&i, sizeof(i)));
618}
619
620TEST_F(ClatdTest, TestGenIIDConfigured) {
621 struct in6_addr myaddr, expected;
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800622 Global_Clatd_Config.use_dynamic_iid = 0;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900623 ASSERT_TRUE(inet_pton(AF_INET6, "::bad:ace:d00d", &Global_Clatd_Config.ipv6_host_id));
624 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:0:bad:ace:d00d", &expected));
625 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &myaddr));
626 config_generate_local_ipv6_subnet(&myaddr);
627 expect_ipv6_addr_equal(&expected, &myaddr);
Lorenzo Colitti2596f422014-11-10 17:00:02 -0800628
629 Global_Clatd_Config.use_dynamic_iid = 1;
630 config_generate_local_ipv6_subnet(&myaddr);
631 EXPECT_FALSE(IN6_ARE_ADDR_EQUAL(&expected, &myaddr));
Lorenzo Colitti98089522014-10-09 22:29:45 +0900632}
633
634TEST_F(ClatdTest, TestGenIIDRandom) {
635 struct in6_addr interface_ipv6;
636 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &interface_ipv6));
637 Global_Clatd_Config.ipv6_host_id = in6addr_any;
638
639 // Generate a boatload of random IIDs.
junyulaic4e591a2018-11-26 22:36:10 +0900640 int onebits = 0;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900641 uint64_t prev_iid = 0;
642 for (int i = 0; i < 100000; i++) {
junyulaic4e591a2018-11-26 22:36:10 +0900643 struct in6_addr myaddr = interface_ipv6;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900644
645 config_generate_local_ipv6_subnet(&myaddr);
646
647 // Check the generated IP address is in the same prefix as the interface IPv6 address.
648 EXPECT_TRUE(ipv6_prefix_equal(&interface_ipv6, &myaddr));
649
650 // Check that consecutive IIDs are not the same.
junyulaic4e591a2018-11-26 22:36:10 +0900651 uint64_t iid = *(uint64_t *)(&myaddr.s6_addr[8]);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900652 ASSERT_TRUE(iid != prev_iid)
653 << "Two consecutive random IIDs are the same: "
654 << std::showbase << std::hex
655 << iid << "\n";
656 prev_iid = iid;
657
658 // Check that the IID is checksum-neutral with the NAT64 prefix and the
659 // local prefix.
junyulaic4e591a2018-11-26 22:36:10 +0900660 struct in_addr *ipv4addr = &Global_Clatd_Config.ipv4_local_subnet;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900661 struct in6_addr *plat_subnet = &Global_Clatd_Config.plat_subnet;
662
663 uint16_t c1 = ip_checksum_finish(ip_checksum_add(0, ipv4addr, sizeof(*ipv4addr)));
664 uint16_t c2 = ip_checksum_finish(ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
665 ip_checksum_add(0, &myaddr, sizeof(myaddr)));
666
667 if (c1 != c2) {
668 char myaddr_str[INET6_ADDRSTRLEN], plat_str[INET6_ADDRSTRLEN], ipv4_str[INET6_ADDRSTRLEN];
669 inet_ntop(AF_INET6, &myaddr, myaddr_str, sizeof(myaddr_str));
670 inet_ntop(AF_INET6, plat_subnet, plat_str, sizeof(plat_str));
671 inet_ntop(AF_INET, ipv4addr, ipv4_str, sizeof(ipv4_str));
672 FAIL()
673 << "Bad IID: " << myaddr_str
674 << " not checksum-neutral with " << ipv4_str << " and " << plat_str
675 << std::showbase << std::hex
676 << "\n IPv4 checksum: " << c1
677 << "\n IPv6 checksum: " << c2
678 << "\n";
679 }
680
681 // Check that IIDs are roughly random and use all the bits by counting the
682 // total number of bits set to 1 in a random sample of 100000 generated IIDs.
683 onebits += count_onebits(&iid, sizeof(iid));
684 }
685 EXPECT_LE(3190000, onebits);
686 EXPECT_GE(3210000, onebits);
687}
688
Lorenzo Colitti798f9932014-10-31 21:54:33 +0900689extern "C" addr_free_func config_is_ipv4_address_free;
690int never_free(in_addr_t /* addr */) { return 0; }
691int always_free(in_addr_t /* addr */) { return 1; }
692int only2_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 2; }
693int over6_free(in_addr_t addr) { return (ntohl(addr) & 0xff) >= 6; }
694int only10_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; }
695
696TEST_F(ClatdTest, SelectIPv4Address) {
697 struct in_addr addr;
698
699 inet_pton(AF_INET, kIPv4LocalAddr, &addr);
700
701 addr_free_func orig_config_is_ipv4_address_free = config_is_ipv4_address_free;
702
703 // If no addresses are free, return INADDR_NONE.
704 config_is_ipv4_address_free = never_free;
705 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
706 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 16));
707
708 // If the configured address is free, pick that. But a prefix that's too big is invalid.
709 config_is_ipv4_address_free = always_free;
710 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 29));
711 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 20));
712 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 15));
713
714 // A prefix length of 32 works, but anything above it is invalid.
715 EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 32));
716 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 33));
717
718 // If another address is free, pick it.
719 config_is_ipv4_address_free = over6_free;
720 EXPECT_EQ(inet_addr("192.0.0.6"), config_select_ipv4_address(&addr, 29));
721
722 // Check that we wrap around to addresses that are lower than the first address.
723 config_is_ipv4_address_free = only2_free;
724 EXPECT_EQ(inet_addr("192.0.0.2"), config_select_ipv4_address(&addr, 29));
725 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 30));
726
727 // If a free address exists outside the prefix, we don't pick it.
728 config_is_ipv4_address_free = only10_free;
729 EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
730 EXPECT_EQ(inet_addr("192.0.0.10"), config_select_ipv4_address(&addr, 24));
731
732 // Now try using the real function which sees if IP addresses are free using bind().
733 // Assume that the machine running the test has the address 127.0.0.1, but not 8.8.8.8.
734 config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
junyulaic4e591a2018-11-26 22:36:10 +0900735 addr.s_addr = inet_addr("8.8.8.8");
Lorenzo Colitti798f9932014-10-31 21:54:33 +0900736 EXPECT_EQ(inet_addr("8.8.8.8"), config_select_ipv4_address(&addr, 29));
737
738 addr.s_addr = inet_addr("127.0.0.1");
739 EXPECT_EQ(inet_addr("127.0.0.2"), config_select_ipv4_address(&addr, 29));
740}
741
Lorenzo Colitti98089522014-10-09 22:29:45 +0900742TEST_F(ClatdTest, DataSanitycheck) {
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900743 // Sanity checks the data.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800744 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900745 ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
746
Brian Carlstromfcac4102014-02-24 20:03:01 -0800747 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900748 ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
749
Brian Carlstromfcac4102014-02-24 20:03:01 -0800750 uint8_t udp_header[] = { UDP_HEADER };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900751 ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
752
753 // Sanity checks check_packet.
754 struct udphdr *udp;
Brian Carlstromfcac4102014-02-24 20:03:01 -0800755 uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900756 udp = (struct udphdr *)(v4_udp_packet + sizeof(struct iphdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900757 fix_udp_checksum(v4_udp_packet);
758 ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
759 check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
760
Brian Carlstromfcac4102014-02-24 20:03:01 -0800761 uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
junyulaic4e591a2018-11-26 22:36:10 +0900762 udp = (struct udphdr *)(v6_udp_packet + sizeof(struct ip6_hdr));
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900763 fix_udp_checksum(v6_udp_packet);
764 ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
765 check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
766
Brian Carlstromfcac4102014-02-24 20:03:01 -0800767 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900768 check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
769
Brian Carlstromfcac4102014-02-24 20:03:01 -0800770 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900771 check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
772
773 // Sanity checks reassemble_packet.
Brian Carlstromfcac4102014-02-24 20:03:01 -0800774 uint8_t reassembled[MAXMTU];
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900775 size_t total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900776 reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), reassembled,
777 &total_length, "Reassembly sanity check");
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900778 check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
779 ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
junyulaic4e591a2018-11-26 22:36:10 +0900780 ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *)reassembled))
781 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900782 check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
783
784 total_length = sizeof(reassembled);
junyulaic4e591a2018-11-26 22:36:10 +0900785 reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments), reassembled,
786 &total_length, "IPv6 reassembly sanity check");
787 ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *)reassembled, total_length))
788 << "Sanity check: reassembled packet is a fragment!\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900789 check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
790}
791
792TEST_F(ClatdTest, PseudoChecksum) {
793 uint32_t pseudo_checksum;
794
junyulaic4e591a2018-11-26 22:36:10 +0900795 uint8_t v4_header[] = { IPV4_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800796 uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900797 pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *)v4_header, UDP_LEN);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900798 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
799 ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900800 << "ipv4_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900801
junyulaic4e591a2018-11-26 22:36:10 +0900802 uint8_t v6_header[] = { IPV6_UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800803 uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
junyulaic4e591a2018-11-26 22:36:10 +0900804 pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *)v6_header, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900805 EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
806 ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
junyulaic4e591a2018-11-26 22:36:10 +0900807 << "ipv6_pseudo_header_checksum incorrect\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900808}
809
810TEST_F(ClatdTest, TransportChecksum) {
junyulaic4e591a2018-11-26 22:36:10 +0900811 uint8_t udphdr[] = { UDP_HEADER };
Brian Carlstromfcac4102014-02-24 20:03:01 -0800812 uint8_t payload[] = { PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900813 EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
junyulaic4e591a2018-11-26 22:36:10 +0900814 << "UDP partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900815 EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
junyulaic4e591a2018-11-26 22:36:10 +0900816 << "Payload partial checksum\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900817
junyulaic4e591a2018-11-26 22:36:10 +0900818 uint8_t ip[] = { IPV4_UDP_HEADER };
819 uint8_t ip6[] = { IPV6_UDP_HEADER };
820 uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *)ip, UDP_LEN);
821 uint32_t ipv6_pseudo_sum =
822 ipv6_pseudo_header_checksum((struct ip6_hdr *)ip6, UDP_LEN, IPPROTO_UDP);
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900823
Ben Cheng932614e2014-04-02 17:00:26 -0700824 EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum) << "IPv4 pseudo-checksum sanity check\n";
825 EXPECT_EQ(0x2644bU, ipv6_pseudo_sum) << "IPv6 pseudo-checksum sanity check\n";
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900826 EXPECT_EQ(
827 kUdpV4Checksum,
828 ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
829 << "Unexpected UDP/IPv4 checksum\n";
830 EXPECT_EQ(
831 kUdpV6Checksum,
832 ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
833 << "Unexpected UDP/IPv6 checksum\n";
834
835 EXPECT_EQ(kUdpV6Checksum,
836 ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
837 << "Adjust IPv4/UDP checksum to IPv6\n";
838 EXPECT_EQ(kUdpV4Checksum,
839 ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
840 << "Adjust IPv6/UDP checksum to IPv4\n";
841}
842
843TEST_F(ClatdTest, AdjustChecksum) {
844 struct checksum_data {
845 uint16_t checksum;
846 uint32_t old_hdr_sum;
847 uint32_t new_hdr_sum;
848 uint16_t result;
849 } DATA[] = {
850 { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
851 { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
852 { 0xdd2f, 0x5555, 0x3285, 0x0000 },
853 { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
854 { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
855 };
Chih-Hung Hsieh05ff5082014-08-26 10:46:26 -0700856 unsigned i = 0;
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900857
858 for (i = 0; i < ARRAYSIZE(DATA); i++) {
859 struct checksum_data *data = DATA + i;
860 uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
861 EXPECT_EQ(result, data->result)
862 << "Incorrect checksum" << std::showbase << std::hex
863 << "\n Expected: " << data->result
864 << "\n Actual: " << result
865 << "\n checksum=" << data->checksum
866 << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
867 }
868}
869
870TEST_F(ClatdTest, Translate) {
Brian Carlstromfcac4102014-02-24 20:03:01 -0800871 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
872 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900873 fix_udp_checksum(udp_ipv4);
874 fix_udp_checksum(udp_ipv6);
875 check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
876 "UDP/IPv4 -> UDP/IPv6 translation");
877 check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
878 "UDP/IPv6 -> UDP/IPv4 translation");
879
Brian Carlstromfcac4102014-02-24 20:03:01 -0800880 uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
881 uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900882 check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
883 "ICMP->ICMPv6 translation");
884 check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
885 "ICMPv6->ICMP translation");
886}
887
888TEST_F(ClatdTest, Fragmentation) {
junyulaic4e591a2018-11-26 22:36:10 +0900889 check_fragment_translation(kIPv4Fragments, kIPv4FragLengths, kIPv6Fragments, kIPv6FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900890 ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
891
junyulaic4e591a2018-11-26 22:36:10 +0900892 check_fragment_translation(kIPv6Fragments, kIPv6FragLengths, kIPv4Fragments, kIPv4FragLengths,
Lorenzo Colittif3beefc2014-02-14 13:19:27 +0900893 ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
894}
Lorenzo Colitti98089522014-10-09 22:29:45 +0900895
896void check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
897 size_t expected_len, const char *msg) {
898 uint8_t translated[MAXMTU];
899 size_t translated_len = sizeof(translated);
900 do_translate_packet(original, original_len, translated, &translated_len, msg);
901 EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
902 // do_translate_packet already checks packets for validity and verifies the checksum.
junyulaic4e591a2018-11-26 22:36:10 +0900903 int original_check = get_transport_checksum(original);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900904 int translated_check = get_transport_checksum(translated);
905 ASSERT_NE(-1, original_check);
906 ASSERT_NE(-1, translated_check);
907 ASSERT_EQ(original_check, translated_check)
junyulaic4e591a2018-11-26 22:36:10 +0900908 << "Not checksum neutral: original and translated checksums differ\n";
Lorenzo Colitti98089522014-10-09 22:29:45 +0900909}
910
911TEST_F(ClatdTest, TranslateChecksumNeutral) {
912 // Generate a random clat IPv6 address and check that translation is checksum-neutral.
913 Global_Clatd_Config.ipv6_host_id = in6addr_any;
914 ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
915 &Global_Clatd_Config.ipv6_local_subnet));
916 config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet);
junyulaic4e591a2018-11-26 22:36:10 +0900917 ASSERT_NE((uint32_t)0x00000464, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
918 ASSERT_NE((uint32_t)0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
Lorenzo Colitti98089522014-10-09 22:29:45 +0900919
920 // Check that translating UDP packets is checksum-neutral. First, IPv4.
921 uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
922 fix_udp_checksum(udp_ipv4);
923 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
924 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
925
926 // Now try IPv6.
927 uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
928 // The test packet uses the static IID, not the random IID. Fix up the source address.
junyulaic4e591a2018-11-26 22:36:10 +0900929 struct ip6_hdr *ip6 = (struct ip6_hdr *)udp_ipv6;
Lorenzo Colitti98089522014-10-09 22:29:45 +0900930 memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
931 fix_udp_checksum(udp_ipv6);
932 check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
933 "UDP/IPv4 -> UDP/IPv6 checksum neutral");
934}