1f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti/*
2f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * Copyright 2014 The Android Open Source Project
3f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti *
4f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License");
5f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * you may not use this file except in compliance with the License.
6f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * You may obtain a copy of the License at
7f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti *
8f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * http://www.apache.org/licenses/LICENSE-2.0
9f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti *
10f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * Unless required by applicable law or agreed to in writing, software
11f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS,
12f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * See the License for the specific language governing permissions and
14f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * limitations under the License.
15f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti *
16f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti * clatd_test.cpp - unit tests for clatd
17f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti */
18f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
19f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include <iostream>
20f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
21f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include <stdio.h>
22f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include <arpa/inet.h>
239808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti#include <netinet/in6.h>
24f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include <sys/uio.h>
25f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
26f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include <gtest/gtest.h>
27f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
28f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiextern "C" {
29f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include "checksum.h"
30f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include "translate.h"
31f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include "config.h"
32f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include "clatd.h"
33f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
34f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
35f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// For convenience.
36f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0])
37f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
38f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// Default translation parameters.
39f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const char kIPv4LocalAddr[] = "192.0.0.4";
40f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
41f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const char kIPv6PlatSubnet[] = "64:ff9b::";
42f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
43f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// Test packet portions. Defined as macros because it's easy to concatenate them to make packets.
44f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_HEADER(p, c1, c2) \
45f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x45, 0x00,    0,   41,  /* Version=4, IHL=5, ToS=0x80, len=41 */     \
46f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x40, 0x00,  /* ID=0x0000, flags=IP_DF, offset=0 */       \
47f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      55,  (p), (c1), (c2),  /* TTL=55, protocol=p, checksum=c1,c2 */     \
48f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti     192,    0,    0,    4,  /* Src=192.0.0.4 */                          \
49f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti       8,    8,    8,    8,  /* Dst=8.8.8.8 */
50f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_UDP_HEADER IPV4_HEADER(IPPROTO_UDP, 0x73, 0xb0)
51f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_ICMP_HEADER IPV4_HEADER(IPPROTO_ICMP, 0x73, 0xc0)
52f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
53f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_HEADER(p) \
54f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x60, 0x00,    0,    0,  /* Version=6, tclass=0x00, flowlabel=0 */    \
55f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti       0,   21,  (p),   55,  /* plen=11, nxthdr=p, hlim=55 */             \
56f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x20, 0x01, 0x0d, 0xb8,  /* Src=2001:db8:0:b11::464 */                \
57f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x0b, 0x11,                                               \
58f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x00, 0x00,                                               \
59f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x04, 0x64,                                               \
60f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x64, 0xff, 0x9b,  /* Dst=64:ff9b::8.8.8.8 */                   \
61f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x00, 0x00,                                               \
62f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x00, 0x00,                                               \
63f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x08, 0x08, 0x08, 0x08,
64f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_UDP_HEADER IPV6_HEADER(IPPROTO_UDP)
65f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_ICMPV6_HEADER IPV6_HEADER(IPPROTO_ICMPV6)
66f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
67f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define UDP_LEN 21
68f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define UDP_HEADER \
69f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0xc8, 0x8b,    0,   53,  /* Port 51339->53 */                         \
70f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, UDP_LEN, 0,    0,  /* Length 21, checksum empty for now */
71f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
72f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define PAYLOAD 'H', 'e', 'l', 'l', 'o', ' ', 0x4e, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0x00
73f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
74f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_PING \
75f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x08, 0x00, 0x88, 0xd0,  /* Type 8, code 0, checksum 0x88d0 */        \
76f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0xd0, 0x0d, 0x00, 0x03,  /* ID=0xd00d, seq=3 */
77f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
78f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_PING \
79f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x80, 0x00, 0xc3, 0x42,  /* Type 128, code 0, checksum 0xc342 */      \
80f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0xd0, 0x0d, 0x00, 0x03,  /* ID=0xd00d, seq=3 */
81f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
82f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// Macros to return pseudo-headers from packets.
83f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_PSEUDOHEADER(ip, tlen)                                  \
84f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip[12], ip[13], ip[14], ip[15],        /* Source address      */   \
85f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip[16], ip[17], ip[18], ip[19],        /* Destination address */   \
86f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  0, ip[9],                              /* 0, protocol         */   \
87f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ((tlen) >> 16) & 0xff, (tlen) & 0xff,  /* Transport length */
88f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
89f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_PSEUDOHEADER(ip6, protocol, tlen)                       \
90f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip6[8],  ip6[9],  ip6[10], ip6[11],  /* Source address */          \
91f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip6[12], ip6[13], ip6[14], ip6[15],                                \
92f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip6[16], ip6[17], ip6[18], ip6[19],                                \
93f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip6[20], ip6[21], ip6[22], ip6[23],                                \
94f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip6[24], ip6[25], ip6[26], ip6[27],  /* Destination address */     \
95f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip6[28], ip6[29], ip6[30], ip6[31],                                \
96f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip6[32], ip6[33], ip6[34], ip6[35],                                \
97f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ip6[36], ip6[37], ip6[38], ip6[39],                                \
98f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ((tlen) >> 24) & 0xff,               /* Transport length */        \
99f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ((tlen) >> 16) & 0xff,                                             \
100f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ((tlen) >> 8) & 0xff,                                              \
101f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  (tlen) & 0xff,                                                     \
102f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  0, 0, 0, (protocol),
103f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
104f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// A fragmented DNS request.
105fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv4Frag1[] = {
106f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x00, 0x40, 0x11,
107f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x8c, 0x6d, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
108f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
109f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x01, 0x00, 0x00, 0x01, 0x00, 0x00
110f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
111fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv4Frag2[] = {
112f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x02, 0x40, 0x11,
113f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x8c, 0x6b, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
114f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06,
115f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65
116f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
117fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv4Frag3[] = {
118f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x45, 0x00, 0x00, 0x1d, 0xfe, 0x47, 0x00, 0x04, 0x40, 0x11,
119f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0xac, 0x70, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
120f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
121f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
122fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t *kIPv4Fragments[] = { kIPv4Frag1, kIPv4Frag2, kIPv4Frag3 };
123fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const size_t kIPv4FragLengths[] = { sizeof(kIPv4Frag1), sizeof(kIPv4Frag2),
124fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom                                           sizeof(kIPv4Frag3) };
125f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
126fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv6Frag1[] = {
127f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
128f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
129f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
130f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
131f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x47, 0x14, 0x5d,
132f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x35, 0x00, 0x29, 0xeb, 0x91, 0x50, 0x47, 0x01, 0x00,
133f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x01, 0x00, 0x00
134f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
135f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
136fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv6Frag2[] = {
137f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01,
138f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
139f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
140f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
141f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0xfe, 0x47, 0x00, 0x00,
142f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f,
143f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x6f, 0x67, 0x6c, 0x65
144f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
145f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
146fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv6Frag3[] = {
147f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x60, 0x00, 0x00, 0x00, 0x00, 0x11, 0x2c, 0x40, 0x20, 0x01,
148f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00,
149f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
150f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
151f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0xfe, 0x47, 0x03, 0x63,
152f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
153f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
154fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t *kIPv6Fragments[] = { kIPv6Frag1, kIPv6Frag2, kIPv6Frag3 };
155fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const size_t kIPv6FragLengths[] = { sizeof(kIPv6Frag1), sizeof(kIPv6Frag2),
156fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom                                           sizeof(kIPv6Frag3) };
157f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
158fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kReassembledIPv4[] = {
159f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x45, 0x00, 0x00, 0x3d, 0xfe, 0x47, 0x00, 0x00, 0x40, 0x11,
160f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0xac, 0x54, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08,
161f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47,
162f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67,
164f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
165f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    0x01
166f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
167f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
168f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// Expected checksums.
169f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const uint32_t kUdpPartialChecksum     = 0xd5c8;
170f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const uint32_t kPayloadPartialChecksum = 0x31e9c;
171f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const uint16_t kUdpV4Checksum          = 0xd0c7;
172f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const uint16_t kUdpV6Checksum          = 0xa74a;
173f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
174fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromuint8_t ip_version(const uint8_t *packet) {
175fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t version = packet[0] >> 4;
176f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  return version;
177f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
178f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
179f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiint is_ipv4_fragment(struct iphdr *ip) {
180f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // A packet is a fragment if its fragment offset is nonzero or if the MF flag is set.
181f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  return ntohs(ip->frag_off) & (IP_OFFMASK | IP_MF);
182f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
183f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
184f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiint is_ipv6_fragment(struct ip6_hdr *ip6, size_t len) {
185f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  if (ip6->ip6_nxt != IPPROTO_FRAGMENT) {
186f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    return 0;
187f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
188f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  struct ip6_frag *frag = (struct ip6_frag *) (ip6 + 1);
189f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  return len >= sizeof(*ip6) + sizeof(*frag) &&
190f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti          (frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG));
191f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
192f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
193f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiint ipv4_fragment_offset(struct iphdr *ip) {
194f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  return ntohs(ip->frag_off) & IP_OFFMASK;
195f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
196f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
197f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiint ipv6_fragment_offset(struct ip6_frag *frag) {
198f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3);
199f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
200f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
201fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_packet(const uint8_t *packet, size_t len, const char *msg) {
202f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  void *payload;
203f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t payload_length = 0;
204f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint32_t pseudo_checksum = 0;
205f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint8_t protocol = 0;
206f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  int version = ip_version(packet);
207f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  switch (version) {
208f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    case 4: {
209f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      struct iphdr *ip = (struct iphdr *) packet;
210f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ASSERT_GE(len, sizeof(*ip)) << msg << ": IPv4 packet shorter than IPv4 header\n";
211f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      EXPECT_EQ(5, ip->ihl) << msg << ": Unsupported IP header length\n";
212f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      EXPECT_EQ(len, ntohs(ip->tot_len)) << msg << ": Incorrect IPv4 length\n";
213f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      EXPECT_EQ(0, ip_checksum(ip, sizeof(*ip))) << msg << ": Incorrect IP checksum\n";
214f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      protocol = ip->protocol;
215f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      payload = ip + 1;
216f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      if (!is_ipv4_fragment(ip)) {
217f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        payload_length = len - sizeof(*ip);
218f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        pseudo_checksum = ipv4_pseudo_header_checksum(ip, payload_length);
219f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      }
220f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP)
221f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti          << msg << ": Unsupported IPv4 protocol " << protocol << "\n";
222f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
223f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
224f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    case 6: {
225f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      struct ip6_hdr *ip6 = (struct ip6_hdr *) packet;
226f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ASSERT_GE(len, sizeof(*ip6)) << msg << ": IPv6 packet shorter than IPv6 header\n";
227f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      EXPECT_EQ(len - sizeof(*ip6), htons(ip6->ip6_plen)) << msg << ": Incorrect IPv6 length\n";
228f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
229f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      if (ip6->ip6_nxt == IPPROTO_FRAGMENT) {
230f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        struct ip6_frag *frag = (struct ip6_frag *) (ip6 + 1);
231f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        ASSERT_GE(len, sizeof(*ip6) + sizeof(*frag))
232f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << msg << ": IPv6 fragment: short fragment header\n";
233f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        protocol = frag->ip6f_nxt;
234f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        payload = frag + 1;
235f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        // Even though the packet has a Fragment header, it might not be a fragment.
236f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        if (!is_ipv6_fragment(ip6, len)) {
237f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti          payload_length = len - sizeof(*ip6) - sizeof(*frag);
238f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        }
239f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      } else {
240f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        // Since there are no extension headers except Fragment, this must be the payload.
241f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        protocol = ip6->ip6_nxt;
242f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        payload = ip6 + 1;
243f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        payload_length = len - sizeof(*ip6);
244f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      }
245f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMPV6)
246f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti          << msg << ": Unsupported IPv6 next header " << protocol;
247f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      if (payload_length) {
248f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        pseudo_checksum = ipv6_pseudo_header_checksum(ip6, payload_length, protocol);
249f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      }
250f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
251f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
252f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    default:
253f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      FAIL() << msg << ": Unsupported IP version " << version << "\n";
254f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      return;
255f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
256f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
257f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // If we understand the payload, verify the checksum.
258f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  if (payload_length) {
259f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint16_t checksum;
260f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    switch(protocol) {
261f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      case IPPROTO_UDP:
262f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      case IPPROTO_TCP:
263f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      case IPPROTO_ICMPV6:
264f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        checksum = ip_checksum_finish(ip_checksum_add(pseudo_checksum, payload, payload_length));
265f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        break;
266f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      case IPPROTO_ICMP:
267f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        checksum = ip_checksum(payload, payload_length);
268f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        break;
269f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      default:
270f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        checksum = 0;  // Don't check.
271f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        break;
272f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
273f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    EXPECT_EQ(0, checksum) << msg << ": Incorrect transport checksum\n";
274f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
275f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
276f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  if (protocol == IPPROTO_UDP) {
277f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    struct udphdr *udp = (struct udphdr *) payload;
278f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    EXPECT_NE(0, udp->check) << msg << ": UDP checksum 0 should be 0xffff";
279f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    // If this is not a fragment, check the UDP length field.
280f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    if (payload_length) {
281f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      EXPECT_EQ(payload_length, ntohs(udp->len)) << msg << ": Incorrect UDP length\n";
282f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
283f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
284f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
285f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
286fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid reassemble_packet(const uint8_t **fragments, const size_t lengths[], int numpackets,
287fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom                       uint8_t *reassembled, size_t *reassembled_len, const char *msg) {
288f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  struct iphdr *ip = NULL;
289f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  struct ip6_hdr *ip6 = NULL;
290932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng  size_t  total_length, pos = 0;
291932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng  uint8_t protocol = 0;
292fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t version = ip_version(fragments[0]);
293f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
294f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  for (int i = 0; i < numpackets; i++) {
295fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom    const uint8_t *packet = fragments[i];
296f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    int len = lengths[i];
297f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    int headersize, payload_offset;
298f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
299f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ASSERT_EQ(ip_version(packet), version) << msg << ": Inconsistent fragment versions\n";
300f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    check_packet(packet, len, "Fragment sanity check");
301f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
302f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    switch (version) {
303f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      case 4: {
304f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        struct iphdr *ip_orig = (struct iphdr *) packet;
305f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        headersize = sizeof(*ip_orig);
306f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        ASSERT_TRUE(is_ipv4_fragment(ip_orig))
307f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n";
308f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip): 0))
309f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n";
310f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
311f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        headersize = sizeof(*ip_orig);
312f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        payload_offset = headersize;
313f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        if (pos == 0) {
314f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti          ip = (struct iphdr *) reassembled;
315f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        }
316f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        break;
317f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      }
318f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      case 6: {
319f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        struct ip6_hdr *ip6_orig = (struct ip6_hdr *) packet;
320f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        struct ip6_frag *frag = (struct ip6_frag *) (ip6_orig + 1);
321f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        ASSERT_TRUE(is_ipv6_fragment(ip6_orig, len))
322f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n";
323f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6): 0))
324f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n";
325f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
326f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        headersize = sizeof(*ip6_orig);
327f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        payload_offset = sizeof(*ip6_orig) + sizeof(*frag);
328f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        if (pos == 0) {
329f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti          ip6 = (struct ip6_hdr *) reassembled;
330f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti          protocol = frag->ip6f_nxt;
331f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        }
332f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        break;
333f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      }
334f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      default:
335f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        FAIL() << msg << ": Invalid IP version << " << version;
336f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
337f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
338f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    // If this is the first fragment, copy the header.
339f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    if (pos == 0) {
340f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ASSERT_LT(headersize, (int) *reassembled_len) << msg << ": Reassembly buffer too small\n";
341f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      memcpy(reassembled, packet, headersize);
342f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      total_length = headersize;
343f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      pos += headersize;
344f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
345f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
346f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    // Copy the payload.
347f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    int payload_length = len - payload_offset;
348f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    total_length += payload_length;
349932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng    ASSERT_LT(total_length, *reassembled_len) << msg << ": Reassembly buffer too small\n";
350f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    memcpy(reassembled + pos, packet + payload_offset, payload_length);
351f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    pos += payload_length;
352f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
353f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
354f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
355f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Fix up the reassembled headers to reflect fragmentation and length (and IPv4 checksum).
356f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(total_length, pos) << msg << ": Reassembled packet length incorrect\n";
357f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  if (ip) {
358f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ip->frag_off &= ~htons(IP_MF);
359f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ip->tot_len = htons(total_length);
360f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ip->check = 0;
361f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ip->check = ip_checksum(ip, sizeof(*ip));
362f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ASSERT_FALSE(is_ipv4_fragment(ip)) << msg << ": reassembled IPv4 packet is a fragment!\n";
363f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
364f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  if (ip6) {
365f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ip6->ip6_nxt = protocol;
366f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ip6->ip6_plen = htons(total_length - sizeof(*ip6));
367f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    ASSERT_FALSE(is_ipv6_fragment(ip6, ip6->ip6_plen))
368f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << msg << ": reassembled IPv6 packet is a fragment!\n";
369f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
370f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
371f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  *reassembled_len = total_length;
372f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
373f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
3749808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittivoid check_data_matches(const void *expected, const void *actual, size_t len, const char *msg) {
375f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  if (memcmp(expected, actual, len)) {
376f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    // Hex dump, 20 bytes per line, one space between bytes (1 byte = 3 chars), indented by 4.
377f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    int hexdump_len = len * 3 + (len / 20 + 1) * 5;
378f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    char expected_hexdump[hexdump_len], actual_hexdump[hexdump_len];
379f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    unsigned pos = 0;
380f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    for (unsigned i = 0; i < len; i++) {
381f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      if (i % 20 == 0) {
3822dcca6feb91fd917e26c4989af6400de904466a2George Burgess IV        snprintf(expected_hexdump + pos, hexdump_len - pos, "\n   ");
3832dcca6feb91fd917e26c4989af6400de904466a2George Burgess IV        snprintf(actual_hexdump + pos, hexdump_len - pos, "\n   ");
384f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        pos += 4;
385f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      }
3862dcca6feb91fd917e26c4989af6400de904466a2George Burgess IV      snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *) expected)[i]);
3872dcca6feb91fd917e26c4989af6400de904466a2George Burgess IV      snprintf(actual_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *) actual)[i]);
388f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      pos += 3;
389f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
3909808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    FAIL() << msg << ": Data doesn't match"
391f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti           << "\n  Expected:" << (char *) expected_hexdump
392f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti           << "\n  Actual:" << (char *) actual_hexdump << "\n";
393f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
394f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
395f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
396fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid fix_udp_checksum(uint8_t* packet) {
397f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint32_t pseudo_checksum;
398fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t version = ip_version(packet);
399f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  struct udphdr *udp;
400f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  switch (version) {
401f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    case 4: {
402f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      struct iphdr *ip = (struct iphdr *) packet;
403f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      udp = (struct udphdr *) (ip + 1);
404f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len));
405f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
406f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
407f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    case 6: {
408f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      struct ip6_hdr *ip6 = (struct ip6_hdr *) packet;
409f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      udp = (struct udphdr *) (ip6 + 1);
410f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP);
411f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
412f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
413f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    default:
414f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      FAIL() << "unsupported IP version" << version << "\n";
415f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      return;
416f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    }
417f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
418f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  udp->check = 0;
419f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  udp->check = ip_checksum_finish(ip_checksum_add(pseudo_checksum, udp, ntohs(udp->len)));
420f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
421f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
422ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti// Testing stub for send_rawv6. The real version uses sendmsg() with a
423ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti// destination IPv6 address, and attempting to call that on our test socketpair
424ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti// fd results in EINVAL.
425ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colittiextern "C" void send_rawv6(int fd, clat_packet out, int iov_len) {
426ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    writev(fd, out, iov_len);
427ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti}
428ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti
429fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *out, size_t *outlen,
430f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                         const char *msg) {
431f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  int fds[2];
432f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, fds)) {
433f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    abort();
434f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
435f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
436f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  char foo[512];
437f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg);
438f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(original, original_len, foo);
439f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
440e24982ea3a4480d9d62c75b4d9a416b9479f7f0bLorenzo Colitti  int read_fd, write_fd;
441f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint16_t expected_proto;
442f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  int version = ip_version(original);
443f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  switch (version) {
444f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    case 4:
445f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      expected_proto = htons(ETH_P_IPV6);
446f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      read_fd = fds[1];
447e24982ea3a4480d9d62c75b4d9a416b9479f7f0bLorenzo Colitti      write_fd = fds[0];
448f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
449f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    case 6:
450f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      expected_proto = htons(ETH_P_IP);
451f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      read_fd = fds[0];
452e24982ea3a4480d9d62c75b4d9a416b9479f7f0bLorenzo Colitti      write_fd = fds[1];
453f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
454f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    default:
455f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      FAIL() << msg << ": Unsupported IP version " << version << "\n";
456f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
457f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
458f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
459e24982ea3a4480d9d62c75b4d9a416b9479f7f0bLorenzo Colitti  translate_packet(write_fd, (version == 4), original, original_len);
460f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
4619808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
462ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti  if (version == 6) {
463ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    // Translating to IPv4. Expect a tun header.
464ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    struct tun_pi new_tun_header;
465ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    struct iovec iov[] = {
466ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti      { &new_tun_header, sizeof(new_tun_header) },
467ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti      { out, *outlen }
468ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    };
469ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    int len = readv(read_fd, iov, 2);
470ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    if (len > (int) sizeof(new_tun_header)) {
471ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti      ASSERT_LT((size_t) len, *outlen) << msg << ": Translated packet buffer too small\n";
472ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti      EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
473ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti      *outlen = len - sizeof(new_tun_header);
4749808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      check_packet(out, *outlen, msg);
475ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    } else {
4769808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      FAIL() << msg << ": Packet was not translated: len=" << len;
477ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti      *outlen = 0;
478ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    }
479f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  } else {
480ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    // Translating to IPv6. Expect raw packet.
481ce14088b80c2d22add83a616e567f9025d252ef7Lorenzo Colitti    *outlen = read(read_fd, out, *outlen);
4829808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    check_packet(out, *outlen, msg);
483f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
484f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
485f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
486fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_translated_packet(const uint8_t *original, size_t original_len,
487fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom                             const uint8_t *expected, size_t expected_len, const char *msg) {
488fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t translated[MAXMTU];
489f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t translated_len = sizeof(translated);
490f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  do_translate_packet(original, original_len, translated, &translated_len, msg);
491f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
492f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_data_matches(expected, translated, translated_len, msg);
493f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
494f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
495fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
496fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom                                const uint8_t *expected[], const size_t expected_lengths[],
497f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                                int numfragments, const char *msg) {
498f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  for (int i = 0; i < numfragments; i++) {
499f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    // Check that each of the fragments translates as expected.
500f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    char frag_msg[512];
501f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
502f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    check_translated_packet(original[i], original_lengths[i],
503f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                            expected[i], expected_lengths[i], frag_msg);
504f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
505f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
506f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Sanity check that reassembling the original and translated fragments produces valid packets.
507fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t reassembled[MAXMTU];
508f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t reassembled_len = sizeof(reassembled);
509f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
510f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(reassembled, reassembled_len, msg);
511f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
512fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t translated[MAXMTU];
513f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t translated_len = sizeof(translated);
514f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
515f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(translated, translated_len, msg);
516f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
517f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
5189808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittiint get_transport_checksum(const uint8_t *packet) {
5199808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct iphdr *ip;
5209808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct ip6_hdr *ip6;
5219808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint8_t protocol;
5229808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  const void *payload;
5239808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5249808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int version = ip_version(packet);
5259808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  switch (version) {
5269808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case 4:
5279808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      ip = (struct iphdr *) packet;
5289808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      if (is_ipv4_fragment(ip)) {
5299808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          return -1;
5309808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      }
5319808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      protocol = ip->protocol;
5329808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      payload = ip + 1;
5339808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      break;
5349808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case 6:
5359808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      ip6 = (struct ip6_hdr *) packet;
5369808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      protocol = ip6->ip6_nxt;
5379808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      payload = ip6 + 1;
5389808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      break;
5399808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    default:
5409808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      return -1;
5419808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
5429808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5439808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  switch (protocol) {
5449808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case IPPROTO_UDP:
5459808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      return ((struct udphdr *) payload)->check;
5469808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5479808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case IPPROTO_TCP:
5489808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      return ((struct tcphdr *) payload)->check;
5499808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5509808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case IPPROTO_FRAGMENT:
5519808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    default:
5529808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      return -1;
5539808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
5549808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
5559808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
556f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistruct clat_config Global_Clatd_Config;
557f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
558f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitticlass ClatdTest : public ::testing::Test {
559f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti protected:
560f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  virtual void SetUp() {
561f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
562f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
563f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
5649808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    Global_Clatd_Config.ipv6_host_id = in6addr_any;
5652596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti    Global_Clatd_Config.use_dynamic_iid = 1;
566f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
567f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
568f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
5699808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittivoid expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
5709808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
5719808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
5729808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
5739808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
5749808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    FAIL()
5759808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "Unexpected IPv6 address:: "
5769808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "\n  Expected: " << expected_str
5779808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "\n  Actual:   " << actual_str
5789808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "\n";
5799808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
5809808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
5819808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5829808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TestIPv6PrefixEqual) {
5839808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
5849808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                &Global_Clatd_Config.plat_subnet));
5859808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
5869808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                 &Global_Clatd_Config.ipv6_local_subnet));
5879808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5889808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
5899808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
5909808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
5919808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5929808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  subnet2.s6_addr[6] = 0xff;
5939808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
5949808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
5959808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
5969808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5979808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittiint count_onebits(const void *data, size_t size) {
5989808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int onebits = 0;
5999808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  for (size_t pos = 0; pos < size; pos++) {
6009808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    uint8_t *byte = ((uint8_t*) data) + pos;
6019808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    for (int shift = 0; shift < 8; shift++) {
6029808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      onebits += (*byte >> shift) & 1;
6039808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    }
6049808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
6059808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  return onebits;
6069808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
6079808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6089808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TestCountOnebits) {
6099808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint64_t i;
6109808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  i = 1;
6119808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
6129808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  i <<= 61;
6139808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
6149808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  i |= ((uint64_t) 1 << 33);
6159808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(2, count_onebits(&i, sizeof(i)));
6169808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  i = 0xf1000202020000f0;
6179808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(5 + 1 + 1 + 1 + 4, count_onebits(&i, sizeof(i)));
6189808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
6199808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6209808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TestGenIIDConfigured) {
6219808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct in6_addr myaddr, expected;
6222596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti  Global_Clatd_Config.use_dynamic_iid = 0;
6239808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "::bad:ace:d00d", &Global_Clatd_Config.ipv6_host_id));
6249808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:0:bad:ace:d00d", &expected));
6259808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &myaddr));
6269808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  config_generate_local_ipv6_subnet(&myaddr);
6279808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  expect_ipv6_addr_equal(&expected, &myaddr);
6282596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti
6292596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti  Global_Clatd_Config.use_dynamic_iid = 1;
6302596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti  config_generate_local_ipv6_subnet(&myaddr);
6312596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti  EXPECT_FALSE(IN6_ARE_ADDR_EQUAL(&expected, &myaddr));
6329808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
6339808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6349808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TestGenIIDRandom) {
6359808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct in6_addr interface_ipv6;
6369808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &interface_ipv6));
6379808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  Global_Clatd_Config.ipv6_host_id = in6addr_any;
6389808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6399808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // Generate a boatload of random IIDs.
6409808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int onebits = 0;
6419808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint64_t prev_iid = 0;
6429808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  for (int i = 0; i < 100000; i++) {
6439808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    struct in6_addr myaddr =  interface_ipv6;
6449808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6459808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    config_generate_local_ipv6_subnet(&myaddr);
6469808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6479808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // Check the generated IP address is in the same prefix as the interface IPv6 address.
6489808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    EXPECT_TRUE(ipv6_prefix_equal(&interface_ipv6, &myaddr));
6499808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6509808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // Check that consecutive IIDs are not the same.
6519808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    uint64_t iid = * (uint64_t*) (&myaddr.s6_addr[8]);
6529808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    ASSERT_TRUE(iid != prev_iid)
6539808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "Two consecutive random IIDs are the same: "
6549808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << std::showbase << std::hex
6559808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << iid << "\n";
6569808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    prev_iid = iid;
6579808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6589808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // Check that the IID is checksum-neutral with the NAT64 prefix and the
6599808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // local prefix.
6609808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    struct in_addr *ipv4addr = &Global_Clatd_Config.ipv4_local_subnet;
6619808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    struct in6_addr *plat_subnet = &Global_Clatd_Config.plat_subnet;
6629808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6639808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    uint16_t c1 = ip_checksum_finish(ip_checksum_add(0, ipv4addr, sizeof(*ipv4addr)));
6649808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    uint16_t c2 = ip_checksum_finish(ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
6659808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                     ip_checksum_add(0, &myaddr, sizeof(myaddr)));
6669808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6679808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    if (c1 != c2) {
6689808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      char myaddr_str[INET6_ADDRSTRLEN], plat_str[INET6_ADDRSTRLEN], ipv4_str[INET6_ADDRSTRLEN];
6699808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      inet_ntop(AF_INET6, &myaddr, myaddr_str, sizeof(myaddr_str));
6709808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      inet_ntop(AF_INET6, plat_subnet, plat_str, sizeof(plat_str));
6719808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      inet_ntop(AF_INET, ipv4addr, ipv4_str, sizeof(ipv4_str));
6729808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      FAIL()
6739808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << "Bad IID: " << myaddr_str
6749808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << " not checksum-neutral with " << ipv4_str << " and " << plat_str
6759808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << std::showbase << std::hex
6769808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << "\n  IPv4 checksum: " << c1
6779808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << "\n  IPv6 checksum: " << c2
6789808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << "\n";
6799808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    }
6809808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6819808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // Check that IIDs are roughly random and use all the bits by counting the
6829808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // total number of bits set to 1 in a random sample of 100000 generated IIDs.
6839808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    onebits += count_onebits(&iid, sizeof(iid));
6849808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
6859808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_LE(3190000, onebits);
6869808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_GE(3210000, onebits);
6879808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
6889808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
689798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiextern "C" addr_free_func config_is_ipv4_address_free;
690798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint never_free(in_addr_t /* addr */) { return 0; }
691798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint always_free(in_addr_t /* addr */) { return 1; }
692798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint only2_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 2; }
693798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint over6_free(in_addr_t addr) { return (ntohl(addr) & 0xff) >= 6; }
694798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint only10_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; }
695798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
696798f9934fca523dfb57136bd185cf6e9460323adLorenzo ColittiTEST_F(ClatdTest, SelectIPv4Address) {
697798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  struct in_addr addr;
698798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
699798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  inet_pton(AF_INET, kIPv4LocalAddr, &addr);
700798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
701798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  addr_free_func orig_config_is_ipv4_address_free = config_is_ipv4_address_free;
702798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
703798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // If no addresses are free, return INADDR_NONE.
704798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = never_free;
705798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
706798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 16));
707798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
708798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // If the configured address is free, pick that. But a prefix that's too big is invalid.
709798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = always_free;
710798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 29));
711798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 20));
712798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 15));
713798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
714798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // A prefix length of 32 works, but anything above it is invalid.
715798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 32));
716798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 33));
717798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
718798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // If another address is free, pick it.
719798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = over6_free;
720798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("192.0.0.6"), config_select_ipv4_address(&addr, 29));
721798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
722798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // Check that we wrap around to addresses that are lower than the first address.
723798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = only2_free;
724798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("192.0.0.2"), config_select_ipv4_address(&addr, 29));
725798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 30));
726798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
727798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // If a free address exists outside the prefix, we don't pick it.
728798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = only10_free;
729798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
730798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("192.0.0.10"), config_select_ipv4_address(&addr, 24));
731798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
732798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // Now try using the real function which sees if IP addresses are free using bind().
733798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // Assume that the machine running the test has the address 127.0.0.1, but not 8.8.8.8.
734798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
735798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  addr.s_addr = inet_addr("8.8.8.8");
736798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("8.8.8.8"), config_select_ipv4_address(&addr, 29));
737798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
738798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  addr.s_addr = inet_addr("127.0.0.1");
739798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("127.0.0.2"), config_select_ipv4_address(&addr, 29));
740798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti}
741798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
7429808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, DataSanitycheck) {
743f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Sanity checks the data.
744fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v4_header[] = { IPV4_UDP_HEADER };
745f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
746f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
747fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v6_header[] = { IPV6_UDP_HEADER };
748f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
749f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
750fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t udp_header[] = { UDP_HEADER };
751f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
752f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
753f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Sanity checks check_packet.
754f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  struct udphdr *udp;
755fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
756f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  udp = (struct udphdr *) (v4_udp_packet + sizeof(struct iphdr));
757f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  fix_udp_checksum(v4_udp_packet);
758f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
759f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
760f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
761fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
762f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  udp = (struct udphdr *) (v6_udp_packet + sizeof(struct ip6_hdr));
763f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  fix_udp_checksum(v6_udp_packet);
764f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
765f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
766f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
767fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
768f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
769f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
770fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
771f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
772f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
773f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Sanity checks reassemble_packet.
774fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t reassembled[MAXMTU];
775f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t total_length = sizeof(reassembled);
776f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments),
777f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                    reassembled, &total_length, "Reassembly sanity check");
778f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
779f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
780f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *) reassembled))
781f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Sanity check: reassembled packet is a fragment!\n";
782f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
783f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
784f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  total_length = sizeof(reassembled);
785f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments),
786f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                    reassembled, &total_length, "IPv6 reassembly sanity check");
787f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *) reassembled, total_length))
788f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Sanity check: reassembled packet is a fragment!\n";
789f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
790f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
791f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
792f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, PseudoChecksum) {
793f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint32_t pseudo_checksum;
794f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
795fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v4_header[] = { IPV4_UDP_HEADER };
796fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
797f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *) v4_header, UDP_LEN);
798f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
799f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
800f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << "ipv4_pseudo_header_checksum incorrect\n";
801f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
802fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v6_header[] = { IPV6_UDP_HEADER };
803fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
804f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *) v6_header, UDP_LEN, IPPROTO_UDP);
805f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
806f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
807f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << "ipv6_pseudo_header_checksum incorrect\n";
808f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
809f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
810f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, TransportChecksum) {
811fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t udphdr[] = { UDP_HEADER };
812fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t payload[] = { PAYLOAD };
813f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
814f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << "UDP partial checksum\n";
815f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
816f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << "Payload partial checksum\n";
817f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
818fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ip[] = { IPV4_UDP_HEADER };
819fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ip6[] = { IPV6_UDP_HEADER };
820f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *) ip, UDP_LEN);
821f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint32_t ipv6_pseudo_sum = ipv6_pseudo_header_checksum((struct ip6_hdr *) ip6, UDP_LEN,
822f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                                                         IPPROTO_UDP);
823f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
824932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng  EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum) << "IPv4 pseudo-checksum sanity check\n";
825932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng  EXPECT_EQ(0x2644bU, ipv6_pseudo_sum) << "IPv6 pseudo-checksum sanity check\n";
826f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(
827f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      kUdpV4Checksum,
828f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
829f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Unexpected UDP/IPv4 checksum\n";
830f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(
831f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      kUdpV6Checksum,
832f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
833f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Unexpected UDP/IPv6 checksum\n";
834f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
835f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(kUdpV6Checksum,
836f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
837f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Adjust IPv4/UDP checksum to IPv6\n";
838f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(kUdpV4Checksum,
839f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
840f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Adjust IPv6/UDP checksum to IPv4\n";
841f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
842f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
843f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, AdjustChecksum) {
844f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  struct checksum_data {
845f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint16_t checksum;
846f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint32_t old_hdr_sum;
847f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint32_t new_hdr_sum;
848f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint16_t result;
849f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  } DATA[] = {
850f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
851f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
852f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0xdd2f, 0x5555, 0x3285, 0x0000 },
853f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
854f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
855f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  };
85605ff508a793c2113ca2a06942f0cec1aec220799Chih-Hung Hsieh  unsigned i = 0;
857f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
858f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  for (i = 0; i < ARRAYSIZE(DATA); i++) {
859f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    struct checksum_data *data = DATA + i;
860f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
861f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    EXPECT_EQ(result, data->result)
862f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << "Incorrect checksum" << std::showbase << std::hex
863f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << "\n  Expected: " << data->result
864f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << "\n  Actual:   " << result
865f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << "\n    checksum=" << data->checksum
866f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
867f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
868f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
869f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
870f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, Translate) {
871fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
872fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
873f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  fix_udp_checksum(udp_ipv4);
874f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  fix_udp_checksum(udp_ipv6);
875f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
876f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                          "UDP/IPv4 -> UDP/IPv6 translation");
877f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
878f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                          "UDP/IPv6 -> UDP/IPv4 translation");
879f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
880fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
881fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
882f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
883f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                          "ICMP->ICMPv6 translation");
884f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
885f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                          "ICMPv6->ICMP translation");
886f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
887f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
888f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, Fragmentation) {
889f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_fragment_translation(kIPv4Fragments, kIPv4FragLengths,
890f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                             kIPv6Fragments, kIPv6FragLengths,
891f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                             ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
892f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
893f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_fragment_translation(kIPv6Fragments, kIPv6FragLengths,
894f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                             kIPv4Fragments, kIPv4FragLengths,
895f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                             ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
896f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
8979808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
8989808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittivoid check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
8999808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                      size_t expected_len, const char *msg) {
9009808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint8_t translated[MAXMTU];
9019808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  size_t translated_len = sizeof(translated);
9029808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  do_translate_packet(original, original_len, translated, &translated_len, msg);
9039808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
9049808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // do_translate_packet already checks packets for validity and verifies the checksum.
9059808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int original_check = get_transport_checksum(original);
9069808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int translated_check = get_transport_checksum(translated);
9079808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_NE(-1, original_check);
9089808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_NE(-1, translated_check);
9099808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(original_check, translated_check)
9109808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      << "Not checksum neutral: original and translated checksums differ\n";
9119808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
9129808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
9139808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TranslateChecksumNeutral) {
9149808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // Generate a random clat IPv6 address and check that translation is checksum-neutral.
9159808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  Global_Clatd_Config.ipv6_host_id = in6addr_any;
9169808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
9179808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                        &Global_Clatd_Config.ipv6_local_subnet));
9189808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet);
9199808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_NE((uint32_t) 0x00000464, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
9209808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_NE((uint32_t) 0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
9219808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
9229808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // Check that translating UDP packets is checksum-neutral. First, IPv4.
9239808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
9249808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  fix_udp_checksum(udp_ipv4);
9259808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
9269808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                   "UDP/IPv4 -> UDP/IPv6 checksum neutral");
9279808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
9289808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // Now try IPv6.
9299808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
9309808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // The test packet uses the static IID, not the random IID. Fix up the source address.
9319808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct ip6_hdr *ip6 = (struct ip6_hdr *) udp_ipv6;
9329808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
9339808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  fix_udp_checksum(udp_ipv6);
9349808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
9359808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                   "UDP/IPv4 -> UDP/IPv6 checksum neutral");
9369808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
937