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