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) {
382f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        sprintf(expected_hexdump + pos, "\n   ");
383f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        sprintf(actual_hexdump + pos, "\n   ");
384f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        pos += 4;
385f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      }
3869808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      sprintf(expected_hexdump + pos, " %02x", ((uint8_t *) expected)[i]);
3879808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      sprintf(actual_hexdump + 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
42210e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti// Testing stub for send_rawv6. The real version uses sendmsg() with a
42310e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti// destination IPv6 address, and attempting to call that on our test socketpair
42410e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti// fd results in EINVAL.
42510e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colittiextern "C" void send_rawv6(int fd, clat_packet out, int iov_len) {
42610e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    writev(fd, out, iov_len);
42710e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti}
42810e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo 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  struct tun_pi tun_header = { 0, 0 };
436f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
437f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  char foo[512];
438f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg);
439f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(original, original_len, foo);
440f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
44191d0f1bc6dd24e54ed3caef9b08525b332ab0adfLorenzo Colitti  int read_fd, write_fd;
442f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint16_t expected_proto;
443f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  int version = ip_version(original);
444f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  switch (version) {
445f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    case 4:
446f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      tun_header.proto = htons(ETH_P_IP);
447f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      expected_proto = htons(ETH_P_IPV6);
448f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      read_fd = fds[1];
44991d0f1bc6dd24e54ed3caef9b08525b332ab0adfLorenzo Colitti      write_fd = fds[0];
450f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
451f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    case 6:
452f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      tun_header.proto = htons(ETH_P_IPV6);
453f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      expected_proto = htons(ETH_P_IP);
454f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      read_fd = fds[0];
45591d0f1bc6dd24e54ed3caef9b08525b332ab0adfLorenzo Colitti      write_fd = fds[1];
456f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
457f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    default:
458f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      FAIL() << msg << ": Unsupported IP version " << version << "\n";
459f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      break;
460f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
461f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
46291d0f1bc6dd24e54ed3caef9b08525b332ab0adfLorenzo Colitti  translate_packet(write_fd, (version == 4), original, original_len);
463f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
4649808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
46510e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti  if (version == 6) {
46610e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    // Translating to IPv4. Expect a tun header.
46710e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    struct tun_pi new_tun_header;
46810e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    struct iovec iov[] = {
46910e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti      { &new_tun_header, sizeof(new_tun_header) },
47010e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti      { out, *outlen }
47110e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    };
47210e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    int len = readv(read_fd, iov, 2);
47310e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    if (len > (int) sizeof(new_tun_header)) {
47410e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti      ASSERT_LT((size_t) len, *outlen) << msg << ": Translated packet buffer too small\n";
47510e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti      EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
47610e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti      *outlen = len - sizeof(new_tun_header);
4779808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      check_packet(out, *outlen, msg);
47810e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    } else {
4799808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      FAIL() << msg << ": Packet was not translated: len=" << len;
48010e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti      *outlen = 0;
48110e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    }
482f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  } else {
48310e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    // Translating to IPv6. Expect raw packet.
48410e8827d636a72a7bcdfd52d15bad9342ae2a0a6Lorenzo Colitti    *outlen = read(read_fd, out, *outlen);
4859808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    check_packet(out, *outlen, msg);
486f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
487f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
488f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
489fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_translated_packet(const uint8_t *original, size_t original_len,
490fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom                             const uint8_t *expected, size_t expected_len, const char *msg) {
491fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t translated[MAXMTU];
492f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t translated_len = sizeof(translated);
493f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  do_translate_packet(original, original_len, translated, &translated_len, msg);
494f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
495f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_data_matches(expected, translated, translated_len, msg);
496f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
497f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
498fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
499fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom                                const uint8_t *expected[], const size_t expected_lengths[],
500f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                                int numfragments, const char *msg) {
501f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  for (int i = 0; i < numfragments; i++) {
502f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    // Check that each of the fragments translates as expected.
503f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    char frag_msg[512];
504f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
505f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    check_translated_packet(original[i], original_lengths[i],
506f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                            expected[i], expected_lengths[i], frag_msg);
507f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
508f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
509f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Sanity check that reassembling the original and translated fragments produces valid packets.
510fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t reassembled[MAXMTU];
511f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t reassembled_len = sizeof(reassembled);
512f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
513f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(reassembled, reassembled_len, msg);
514f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
515fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t translated[MAXMTU];
516f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t translated_len = sizeof(translated);
517f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
518f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(translated, translated_len, msg);
519f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
520f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
5219808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittiint get_transport_checksum(const uint8_t *packet) {
5229808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct iphdr *ip;
5239808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct ip6_hdr *ip6;
5249808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint8_t protocol;
5259808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  const void *payload;
5269808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5279808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int version = ip_version(packet);
5289808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  switch (version) {
5299808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case 4:
5309808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      ip = (struct iphdr *) packet;
5319808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      if (is_ipv4_fragment(ip)) {
5329808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          return -1;
5339808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      }
5349808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      protocol = ip->protocol;
5359808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      payload = ip + 1;
5369808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      break;
5379808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case 6:
5389808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      ip6 = (struct ip6_hdr *) packet;
5399808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      protocol = ip6->ip6_nxt;
5409808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      payload = ip6 + 1;
5419808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      break;
5429808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    default:
5439808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      return -1;
5449808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
5459808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5469808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  switch (protocol) {
5479808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case IPPROTO_UDP:
5489808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      return ((struct udphdr *) payload)->check;
5499808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5509808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case IPPROTO_TCP:
5519808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      return ((struct tcphdr *) payload)->check;
5529808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5539808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    case IPPROTO_FRAGMENT:
5549808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    default:
5559808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      return -1;
5569808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
5579808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
5589808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
559f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistruct clat_config Global_Clatd_Config;
560f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
561f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitticlass ClatdTest : public ::testing::Test {
562f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti protected:
563f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  virtual void SetUp() {
564f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
565f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
566f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
5679808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    Global_Clatd_Config.ipv6_host_id = in6addr_any;
5682596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti    Global_Clatd_Config.use_dynamic_iid = 1;
569f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
570f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti};
571f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
5729808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittivoid expect_ipv6_addr_equal(struct in6_addr *expected, struct in6_addr *actual) {
5739808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  if (!IN6_ARE_ADDR_EQUAL(expected, actual)) {
5749808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    char expected_str[INET6_ADDRSTRLEN], actual_str[INET6_ADDRSTRLEN];
5759808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    inet_ntop(AF_INET6, expected, expected_str, sizeof(expected_str));
5769808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    inet_ntop(AF_INET6, actual, actual_str, sizeof(actual_str));
5779808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    FAIL()
5789808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "Unexpected IPv6 address:: "
5799808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "\n  Expected: " << expected_str
5809808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "\n  Actual:   " << actual_str
5819808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "\n";
5829808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
5839808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
5849808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5859808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TestIPv6PrefixEqual) {
5869808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
5879808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                &Global_Clatd_Config.plat_subnet));
5889808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.plat_subnet,
5899808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                 &Global_Clatd_Config.ipv6_local_subnet));
5909808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5919808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct in6_addr subnet2 = Global_Clatd_Config.ipv6_local_subnet;
5929808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_TRUE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
5939808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_TRUE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
5949808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
5959808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  subnet2.s6_addr[6] = 0xff;
5969808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_FALSE(ipv6_prefix_equal(&Global_Clatd_Config.ipv6_local_subnet, &subnet2));
5979808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_FALSE(ipv6_prefix_equal(&subnet2, &Global_Clatd_Config.ipv6_local_subnet));
5989808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
5999808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6009808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittiint count_onebits(const void *data, size_t size) {
6019808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int onebits = 0;
6029808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  for (size_t pos = 0; pos < size; pos++) {
6039808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    uint8_t *byte = ((uint8_t*) data) + pos;
6049808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    for (int shift = 0; shift < 8; shift++) {
6059808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      onebits += (*byte >> shift) & 1;
6069808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    }
6079808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
6089808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  return onebits;
6099808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
6109808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6119808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TestCountOnebits) {
6129808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint64_t i;
6139808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  i = 1;
6149808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
6159808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  i <<= 61;
6169808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
6179808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  i |= ((uint64_t) 1 << 33);
6189808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(2, count_onebits(&i, sizeof(i)));
6199808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  i = 0xf1000202020000f0;
6209808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(5 + 1 + 1 + 1 + 4, count_onebits(&i, sizeof(i)));
6219808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
6229808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6239808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TestGenIIDConfigured) {
6249808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct in6_addr myaddr, expected;
6252596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti  Global_Clatd_Config.use_dynamic_iid = 0;
6269808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "::bad:ace:d00d", &Global_Clatd_Config.ipv6_host_id));
6279808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:0:bad:ace:d00d", &expected));
6289808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &myaddr));
6299808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  config_generate_local_ipv6_subnet(&myaddr);
6309808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  expect_ipv6_addr_equal(&expected, &myaddr);
6312596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti
6322596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti  Global_Clatd_Config.use_dynamic_iid = 1;
6332596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti  config_generate_local_ipv6_subnet(&myaddr);
6342596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti  EXPECT_FALSE(IN6_ARE_ADDR_EQUAL(&expected, &myaddr));
6359808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
6369808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6379808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TestGenIIDRandom) {
6389808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct in6_addr interface_ipv6;
6399808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54", &interface_ipv6));
6409808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  Global_Clatd_Config.ipv6_host_id = in6addr_any;
6419808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6429808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // Generate a boatload of random IIDs.
6439808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int onebits = 0;
6449808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint64_t prev_iid = 0;
6459808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  for (int i = 0; i < 100000; i++) {
6469808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    struct in6_addr myaddr =  interface_ipv6;
6479808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6489808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    config_generate_local_ipv6_subnet(&myaddr);
6499808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6509808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // Check the generated IP address is in the same prefix as the interface IPv6 address.
6519808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    EXPECT_TRUE(ipv6_prefix_equal(&interface_ipv6, &myaddr));
6529808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6539808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // Check that consecutive IIDs are not the same.
6549808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    uint64_t iid = * (uint64_t*) (&myaddr.s6_addr[8]);
6559808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    ASSERT_TRUE(iid != prev_iid)
6569808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << "Two consecutive random IIDs are the same: "
6579808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << std::showbase << std::hex
6589808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti        << iid << "\n";
6599808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    prev_iid = iid;
6609808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6619808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // Check that the IID is checksum-neutral with the NAT64 prefix and the
6629808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // local prefix.
6639808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    struct in_addr *ipv4addr = &Global_Clatd_Config.ipv4_local_subnet;
6649808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    struct in6_addr *plat_subnet = &Global_Clatd_Config.plat_subnet;
6659808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6669808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    uint16_t c1 = ip_checksum_finish(ip_checksum_add(0, ipv4addr, sizeof(*ipv4addr)));
6679808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    uint16_t c2 = ip_checksum_finish(ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
6689808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                     ip_checksum_add(0, &myaddr, sizeof(myaddr)));
6699808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6709808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    if (c1 != c2) {
6719808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      char myaddr_str[INET6_ADDRSTRLEN], plat_str[INET6_ADDRSTRLEN], ipv4_str[INET6_ADDRSTRLEN];
6729808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      inet_ntop(AF_INET6, &myaddr, myaddr_str, sizeof(myaddr_str));
6739808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      inet_ntop(AF_INET6, plat_subnet, plat_str, sizeof(plat_str));
6749808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      inet_ntop(AF_INET, ipv4addr, ipv4_str, sizeof(ipv4_str));
6759808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      FAIL()
6769808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << "Bad IID: " << myaddr_str
6779808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << " not checksum-neutral with " << ipv4_str << " and " << plat_str
6789808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << std::showbase << std::hex
6799808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << "\n  IPv4 checksum: " << c1
6809808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << "\n  IPv6 checksum: " << c2
6819808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti          << "\n";
6829808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    }
6839808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
6849808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // Check that IIDs are roughly random and use all the bits by counting the
6859808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    // total number of bits set to 1 in a random sample of 100000 generated IIDs.
6869808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti    onebits += count_onebits(&iid, sizeof(iid));
6879808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  }
6889808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_LE(3190000, onebits);
6899808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_GE(3210000, onebits);
6909808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
6919808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
692798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiextern "C" addr_free_func config_is_ipv4_address_free;
693798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint never_free(in_addr_t /* addr */) { return 0; }
694798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint always_free(in_addr_t /* addr */) { return 1; }
695798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint only2_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 2; }
696798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint over6_free(in_addr_t addr) { return (ntohl(addr) & 0xff) >= 6; }
697798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint only10_free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; }
698798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
699798f9934fca523dfb57136bd185cf6e9460323adLorenzo ColittiTEST_F(ClatdTest, SelectIPv4Address) {
700798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  struct in_addr addr;
701798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
702798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  inet_pton(AF_INET, kIPv4LocalAddr, &addr);
703798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
704798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  addr_free_func orig_config_is_ipv4_address_free = config_is_ipv4_address_free;
705798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
706798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // If no addresses are free, return INADDR_NONE.
707798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = never_free;
708798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
709798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 16));
710798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
711798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // If the configured address is free, pick that. But a prefix that's too big is invalid.
712798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = always_free;
713798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 29));
714798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 20));
715798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 15));
716798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
717798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // A prefix length of 32 works, but anything above it is invalid.
718798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr(kIPv4LocalAddr), config_select_ipv4_address(&addr, 32));
719798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 33));
720798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
721798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // If another address is free, pick it.
722798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = over6_free;
723798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("192.0.0.6"), config_select_ipv4_address(&addr, 29));
724798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
725798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // Check that we wrap around to addresses that are lower than the first address.
726798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = only2_free;
727798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("192.0.0.2"), config_select_ipv4_address(&addr, 29));
728798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 30));
729798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
730798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // If a free address exists outside the prefix, we don't pick it.
731798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = only10_free;
732798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(INADDR_NONE, config_select_ipv4_address(&addr, 29));
733798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("192.0.0.10"), config_select_ipv4_address(&addr, 24));
734798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
735798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // Now try using the real function which sees if IP addresses are free using bind().
736798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  // Assume that the machine running the test has the address 127.0.0.1, but not 8.8.8.8.
737798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
738798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  addr.s_addr = inet_addr("8.8.8.8");
739798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("8.8.8.8"), config_select_ipv4_address(&addr, 29));
740798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
741798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  addr.s_addr = inet_addr("127.0.0.1");
742798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti  EXPECT_EQ(inet_addr("127.0.0.2"), config_select_ipv4_address(&addr, 29));
743798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti}
744798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti
7459808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, DataSanitycheck) {
746f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Sanity checks the data.
747fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v4_header[] = { IPV4_UDP_HEADER };
748f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n";
749f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
750fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v6_header[] = { IPV6_UDP_HEADER };
751f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n";
752f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
753fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t udp_header[] = { UDP_HEADER };
754f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n";
755f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
756f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Sanity checks check_packet.
757f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  struct udphdr *udp;
758fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
759f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  udp = (struct udphdr *) (v4_udp_packet + sizeof(struct iphdr));
760f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  fix_udp_checksum(v4_udp_packet);
761f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
762f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
763f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
764fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
765f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  udp = (struct udphdr *) (v6_udp_packet + sizeof(struct ip6_hdr));
766f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  fix_udp_checksum(v6_udp_packet);
767f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
768f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
769f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
770fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
771f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check");
772f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
773fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
774f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
775f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
776f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  // Sanity checks reassemble_packet.
777fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t reassembled[MAXMTU];
778f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  size_t total_length = sizeof(reassembled);
779f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments),
780f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                    reassembled, &total_length, "Reassembly sanity check");
781f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
782f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
783f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *) reassembled))
784f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Sanity check: reassembled packet is a fragment!\n";
785f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
786f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
787f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  total_length = sizeof(reassembled);
788f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments),
789f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                    reassembled, &total_length, "IPv6 reassembly sanity check");
790f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *) reassembled, total_length))
791f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Sanity check: reassembled packet is a fragment!\n";
792f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
793f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
794f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
795f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, PseudoChecksum) {
796f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint32_t pseudo_checksum;
797f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
798fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v4_header[] = { IPV4_UDP_HEADER };
799fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
800f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *) v4_header, UDP_LEN);
801f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
802f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
803f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << "ipv4_pseudo_header_checksum incorrect\n";
804f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
805fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v6_header[] = { IPV6_UDP_HEADER };
806fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
807f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *) v6_header, UDP_LEN, IPPROTO_UDP);
808f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
809f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
810f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << "ipv6_pseudo_header_checksum incorrect\n";
811f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
812f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
813f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, TransportChecksum) {
814fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t udphdr[] = { UDP_HEADER };
815fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t payload[] = { PAYLOAD };
816f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
817f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << "UDP partial checksum\n";
818f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
819f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti            << "Payload partial checksum\n";
820f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
821fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ip[] = { IPV4_UDP_HEADER };
822fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ip6[] = { IPV6_UDP_HEADER };
823f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *) ip, UDP_LEN);
824f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  uint32_t ipv6_pseudo_sum = ipv6_pseudo_header_checksum((struct ip6_hdr *) ip6, UDP_LEN,
825f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                                                         IPPROTO_UDP);
826f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
827932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng  EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum) << "IPv4 pseudo-checksum sanity check\n";
828932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng  EXPECT_EQ(0x2644bU, ipv6_pseudo_sum) << "IPv6 pseudo-checksum sanity check\n";
829f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(
830f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      kUdpV4Checksum,
831f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
832f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Unexpected UDP/IPv4 checksum\n";
833f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(
834f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      kUdpV6Checksum,
835f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum))
836f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Unexpected UDP/IPv6 checksum\n";
837f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
838f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(kUdpV6Checksum,
839f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum))
840f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Adjust IPv4/UDP checksum to IPv6\n";
841f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  EXPECT_EQ(kUdpV4Checksum,
842f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum))
843f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti      << "Adjust IPv6/UDP checksum to IPv4\n";
844f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
845f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
846f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, AdjustChecksum) {
847f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  struct checksum_data {
848f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint16_t checksum;
849f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint32_t old_hdr_sum;
850f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint32_t new_hdr_sum;
851f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint16_t result;
852f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  } DATA[] = {
853f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 },
854f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 },
855f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0xdd2f, 0x5555, 0x3285, 0x0000 },
856f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0x1215, 0x5560, 0x15560 + 20, 0x1200 },
857f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a },
858f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  };
859f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  unsigned i, failed = 0;
860f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
861f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  for (i = 0; i < ARRAYSIZE(DATA); i++) {
862f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    struct checksum_data *data = DATA + i;
863f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum);
864f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti    EXPECT_EQ(result, data->result)
865f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << "Incorrect checksum" << std::showbase << std::hex
866f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << "\n  Expected: " << data->result
867f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << "\n  Actual:   " << result
868f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << "\n    checksum=" << data->checksum
869f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti        << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n";
870f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  }
871f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
872f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
873f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, Translate) {
874fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
875fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
876f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  fix_udp_checksum(udp_ipv4);
877f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  fix_udp_checksum(udp_ipv6);
878f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6),
879f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                          "UDP/IPv4 -> UDP/IPv6 translation");
880f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4),
881f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                          "UDP/IPv6 -> UDP/IPv4 translation");
882f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
883fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD };
884fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom  uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD };
885f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping),
886f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                          "ICMP->ICMPv6 translation");
887f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping),
888f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                          "ICMPv6->ICMP translation");
889f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
890f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
891f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, Fragmentation) {
892f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  int len, i;
893f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_fragment_translation(kIPv4Fragments, kIPv4FragLengths,
894f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                             kIPv6Fragments, kIPv6FragLengths,
895f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                             ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
896f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti
897f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti  check_fragment_translation(kIPv6Fragments, kIPv6FragLengths,
898f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                             kIPv4Fragments, kIPv4FragLengths,
899f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti                             ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
900f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}
9019808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
9029808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittivoid check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
9039808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                      size_t expected_len, const char *msg) {
9049808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint8_t translated[MAXMTU];
9059808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  size_t translated_len = sizeof(translated);
9069808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  do_translate_packet(original, original_len, translated, &translated_len, msg);
9079808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
9089808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // do_translate_packet already checks packets for validity and verifies the checksum.
9099808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int original_check = get_transport_checksum(original);
9109808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  int translated_check = get_transport_checksum(translated);
9119808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_NE(-1, original_check);
9129808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_NE(-1, translated_check);
9139808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_EQ(original_check, translated_check)
9149808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti      << "Not checksum neutral: original and translated checksums differ\n";
9159808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
9169808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
9179808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo ColittiTEST_F(ClatdTest, TranslateChecksumNeutral) {
9189808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // Generate a random clat IPv6 address and check that translation is checksum-neutral.
9199808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  Global_Clatd_Config.ipv6_host_id = in6addr_any;
9209808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
9219808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                        &Global_Clatd_Config.ipv6_local_subnet));
9229808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet);
9239808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_NE((uint32_t) 0x00000464, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
9249808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  ASSERT_NE((uint32_t) 0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
9259808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
9269808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // Check that translating UDP packets is checksum-neutral. First, IPv4.
9279808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
9289808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  fix_udp_checksum(udp_ipv4);
9299808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
9309808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                   "UDP/IPv4 -> UDP/IPv6 checksum neutral");
9319808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti
9329808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // Now try IPv6.
9339808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
9349808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  // The test packet uses the static IID, not the random IID. Fix up the source address.
9359808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  struct ip6_hdr *ip6 = (struct ip6_hdr *) udp_ipv6;
9369808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
9379808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  fix_udp_checksum(udp_ipv6);
9389808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti  check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
9399808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti                                   "UDP/IPv4 -> UDP/IPv6 checksum neutral");
9409808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti}
941