clatd_test.cpp revision 91d0f1bc6dd24e54ed3caef9b08525b332ab0adf
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> 23f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include <sys/uio.h> 24f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 25f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include <gtest/gtest.h> 26f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 27f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiextern "C" { 28f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include "checksum.h" 29f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include "translate.h" 30f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include "config.h" 31f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#include "clatd.h" 32f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 33f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 34f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// For convenience. 35f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0]) 36f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 37f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// Default translation parameters. 38f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const char kIPv4LocalAddr[] = "192.0.0.4"; 39f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const char kIPv6LocalAddr[] = "2001:db8:0:b11::464"; 40f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const char kIPv6PlatSubnet[] = "64:ff9b::"; 41f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 42f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// Test packet portions. Defined as macros because it's easy to concatenate them to make packets. 43f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_HEADER(p, c1, c2) \ 44f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x45, 0x00, 0, 41, /* Version=4, IHL=5, ToS=0x80, len=41 */ \ 45f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x40, 0x00, /* ID=0x0000, flags=IP_DF, offset=0 */ \ 46f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 55, (p), (c1), (c2), /* TTL=55, protocol=p, checksum=c1,c2 */ \ 47f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 192, 0, 0, 4, /* Src=192.0.0.4 */ \ 48f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 8, 8, 8, 8, /* Dst=8.8.8.8 */ 49f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_UDP_HEADER IPV4_HEADER(IPPROTO_UDP, 0x73, 0xb0) 50f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_ICMP_HEADER IPV4_HEADER(IPPROTO_ICMP, 0x73, 0xc0) 51f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 52f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_HEADER(p) \ 53f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x60, 0x00, 0, 0, /* Version=6, tclass=0x00, flowlabel=0 */ \ 54f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0, 21, (p), 55, /* plen=11, nxthdr=p, hlim=55 */ \ 55f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x20, 0x01, 0x0d, 0xb8, /* Src=2001:db8:0:b11::464 */ \ 56f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x0b, 0x11, \ 57f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x00, 0x00, \ 58f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x04, 0x64, \ 59f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x64, 0xff, 0x9b, /* Dst=64:ff9b::8.8.8.8 */ \ 60f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x00, 0x00, \ 61f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x00, 0x00, \ 62f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x08, 0x08, 0x08, 0x08, 63f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_UDP_HEADER IPV6_HEADER(IPPROTO_UDP) 64f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_ICMPV6_HEADER IPV6_HEADER(IPPROTO_ICMPV6) 65f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 66f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define UDP_LEN 21 67f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define UDP_HEADER \ 68f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0xc8, 0x8b, 0, 53, /* Port 51339->53 */ \ 69f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, UDP_LEN, 0, 0, /* Length 21, checksum empty for now */ 70f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 71f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define PAYLOAD 'H', 'e', 'l', 'l', 'o', ' ', 0x4e, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0x00 72f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 73f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_PING \ 74f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x08, 0x00, 0x88, 0xd0, /* Type 8, code 0, checksum 0x88d0 */ \ 75f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */ 76f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 77f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_PING \ 78f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x80, 0x00, 0xc3, 0x42, /* Type 128, code 0, checksum 0xc342 */ \ 79f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0xd0, 0x0d, 0x00, 0x03, /* ID=0xd00d, seq=3 */ 80f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 81f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// Macros to return pseudo-headers from packets. 82f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV4_PSEUDOHEADER(ip, tlen) \ 83f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip[12], ip[13], ip[14], ip[15], /* Source address */ \ 84f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip[16], ip[17], ip[18], ip[19], /* Destination address */ \ 85f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0, ip[9], /* 0, protocol */ \ 86f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ((tlen) >> 16) & 0xff, (tlen) & 0xff, /* Transport length */ 87f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 88f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti#define IPV6_PSEUDOHEADER(ip6, protocol, tlen) \ 89f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6[8], ip6[9], ip6[10], ip6[11], /* Source address */ \ 90f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6[12], ip6[13], ip6[14], ip6[15], \ 91f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6[16], ip6[17], ip6[18], ip6[19], \ 92f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6[20], ip6[21], ip6[22], ip6[23], \ 93f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6[24], ip6[25], ip6[26], ip6[27], /* Destination address */ \ 94f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6[28], ip6[29], ip6[30], ip6[31], \ 95f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6[32], ip6[33], ip6[34], ip6[35], \ 96f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6[36], ip6[37], ip6[38], ip6[39], \ 97f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ((tlen) >> 24) & 0xff, /* Transport length */ \ 98f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ((tlen) >> 16) & 0xff, \ 99f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ((tlen) >> 8) & 0xff, \ 100f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti (tlen) & 0xff, \ 101f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0, 0, 0, (protocol), 102f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 103f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// A fragmented DNS request. 104fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv4Frag1[] = { 105f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x00, 0x40, 0x11, 106f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x8c, 0x6d, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 107f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47, 108f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x01, 0x00, 0x00, 0x01, 0x00, 0x00 109f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}; 110fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv4Frag2[] = { 111f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x45, 0x00, 0x00, 0x24, 0xfe, 0x47, 0x20, 0x02, 0x40, 0x11, 112f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x8c, 0x6b, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 113f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 114f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65 115f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}; 116fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv4Frag3[] = { 117f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x45, 0x00, 0x00, 0x1d, 0xfe, 0x47, 0x00, 0x04, 0x40, 0x11, 118f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0xac, 0x70, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 119f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 120f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}; 121fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t *kIPv4Fragments[] = { kIPv4Frag1, kIPv4Frag2, kIPv4Frag3 }; 122fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const size_t kIPv4FragLengths[] = { sizeof(kIPv4Frag1), sizeof(kIPv4Frag2), 123fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom sizeof(kIPv4Frag3) }; 124f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 125fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv6Frag1[] = { 126f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01, 127f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00, 128f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00, 129f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 130f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x47, 0x14, 0x5d, 131f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x35, 0x00, 0x29, 0xeb, 0x91, 0x50, 0x47, 0x01, 0x00, 132f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x01, 0x00, 0x00 133f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}; 134f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 135fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv6Frag2[] = { 136f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0x40, 0x20, 0x01, 137f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00, 138f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00, 139f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 140f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0xfe, 0x47, 0x00, 0x00, 141f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f, 142f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x6f, 0x67, 0x6c, 0x65 143f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}; 144f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 145fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kIPv6Frag3[] = { 146f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x60, 0x00, 0x00, 0x00, 0x00, 0x11, 0x2c, 0x40, 0x20, 0x01, 147f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x0d, 0xb8, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x00, 0x00, 0x00, 148f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x04, 0x64, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00, 149f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 150f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0xfe, 0x47, 0x03, 0x63, 151f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 152f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}; 153fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t *kIPv6Fragments[] = { kIPv6Frag1, kIPv6Frag2, kIPv6Frag3 }; 154fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const size_t kIPv6FragLengths[] = { sizeof(kIPv6Frag1), sizeof(kIPv6Frag2), 155fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom sizeof(kIPv6Frag3) }; 156f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 157fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromstatic const uint8_t kReassembledIPv4[] = { 158f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x45, 0x00, 0x00, 0x3d, 0xfe, 0x47, 0x00, 0x00, 0x40, 0x11, 159f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0xac, 0x54, 0xc0, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 160f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x14, 0x5d, 0x00, 0x35, 0x00, 0x29, 0x68, 0xbb, 0x50, 0x47, 161f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 162f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x04, 0x69, 0x70, 0x76, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67, 163f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 164f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 0x01 165f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}; 166f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 167f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti// Expected checksums. 168f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const uint32_t kUdpPartialChecksum = 0xd5c8; 169f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const uint32_t kPayloadPartialChecksum = 0x31e9c; 170f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const uint16_t kUdpV4Checksum = 0xd0c7; 171f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistatic const uint16_t kUdpV6Checksum = 0xa74a; 172f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 173fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromuint8_t ip_version(const uint8_t *packet) { 174fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t version = packet[0] >> 4; 175f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti return version; 176f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 177f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 178f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiint is_ipv4_fragment(struct iphdr *ip) { 179f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // A packet is a fragment if its fragment offset is nonzero or if the MF flag is set. 180f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti return ntohs(ip->frag_off) & (IP_OFFMASK | IP_MF); 181f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 182f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 183f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiint is_ipv6_fragment(struct ip6_hdr *ip6, size_t len) { 184f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (ip6->ip6_nxt != IPPROTO_FRAGMENT) { 185f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti return 0; 186f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 187f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct ip6_frag *frag = (struct ip6_frag *) (ip6 + 1); 188f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti return len >= sizeof(*ip6) + sizeof(*frag) && 189f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti (frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG)); 190f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 191f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 192f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiint ipv4_fragment_offset(struct iphdr *ip) { 193f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti return ntohs(ip->frag_off) & IP_OFFMASK; 194f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 195f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 196f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittiint ipv6_fragment_offset(struct ip6_frag *frag) { 197f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti return ntohs((frag->ip6f_offlg & IP6F_OFF_MASK) >> 3); 198f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 199f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 200fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_packet(const uint8_t *packet, size_t len, const char *msg) { 201f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti void *payload; 202f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti size_t payload_length = 0; 203f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint32_t pseudo_checksum = 0; 204f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint8_t protocol = 0; 205f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int version = ip_version(packet); 206f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti switch (version) { 207f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case 4: { 208f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct iphdr *ip = (struct iphdr *) packet; 209f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_GE(len, sizeof(*ip)) << msg << ": IPv4 packet shorter than IPv4 header\n"; 210f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(5, ip->ihl) << msg << ": Unsupported IP header length\n"; 211f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(len, ntohs(ip->tot_len)) << msg << ": Incorrect IPv4 length\n"; 212f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(0, ip_checksum(ip, sizeof(*ip))) << msg << ": Incorrect IP checksum\n"; 213f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti protocol = ip->protocol; 214f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti payload = ip + 1; 215f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (!is_ipv4_fragment(ip)) { 216f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti payload_length = len - sizeof(*ip); 217f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pseudo_checksum = ipv4_pseudo_header_checksum(ip, payload_length); 218f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 219f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP) 220f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << msg << ": Unsupported IPv4 protocol " << protocol << "\n"; 221f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 222f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 223f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case 6: { 224f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct ip6_hdr *ip6 = (struct ip6_hdr *) packet; 225f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_GE(len, sizeof(*ip6)) << msg << ": IPv6 packet shorter than IPv6 header\n"; 226f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(len - sizeof(*ip6), htons(ip6->ip6_plen)) << msg << ": Incorrect IPv6 length\n"; 227f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 228f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (ip6->ip6_nxt == IPPROTO_FRAGMENT) { 229f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct ip6_frag *frag = (struct ip6_frag *) (ip6 + 1); 230f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_GE(len, sizeof(*ip6) + sizeof(*frag)) 231f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << msg << ": IPv6 fragment: short fragment header\n"; 232f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti protocol = frag->ip6f_nxt; 233f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti payload = frag + 1; 234f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Even though the packet has a Fragment header, it might not be a fragment. 235f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (!is_ipv6_fragment(ip6, len)) { 236f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti payload_length = len - sizeof(*ip6) - sizeof(*frag); 237f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 238f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } else { 239f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Since there are no extension headers except Fragment, this must be the payload. 240f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti protocol = ip6->ip6_nxt; 241f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti payload = ip6 + 1; 242f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti payload_length = len - sizeof(*ip6); 243f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 244f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMPV6) 245f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << msg << ": Unsupported IPv6 next header " << protocol; 246f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (payload_length) { 247f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pseudo_checksum = ipv6_pseudo_header_checksum(ip6, payload_length, protocol); 248f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 249f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 250f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 251f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti default: 252f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti FAIL() << msg << ": Unsupported IP version " << version << "\n"; 253f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti return; 254f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 255f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 256f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // If we understand the payload, verify the checksum. 257f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (payload_length) { 258f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint16_t checksum; 259f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti switch(protocol) { 260f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case IPPROTO_UDP: 261f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case IPPROTO_TCP: 262f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case IPPROTO_ICMPV6: 263f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti checksum = ip_checksum_finish(ip_checksum_add(pseudo_checksum, payload, payload_length)); 264f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 265f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case IPPROTO_ICMP: 266f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti checksum = ip_checksum(payload, payload_length); 267f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 268f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti default: 269f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti checksum = 0; // Don't check. 270f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 271f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 272f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(0, checksum) << msg << ": Incorrect transport checksum\n"; 273f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 274f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 275f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (protocol == IPPROTO_UDP) { 276f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct udphdr *udp = (struct udphdr *) payload; 277f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_NE(0, udp->check) << msg << ": UDP checksum 0 should be 0xffff"; 278f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // If this is not a fragment, check the UDP length field. 279f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (payload_length) { 280f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(payload_length, ntohs(udp->len)) << msg << ": Incorrect UDP length\n"; 281f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 282f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 283f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 284f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 285fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid reassemble_packet(const uint8_t **fragments, const size_t lengths[], int numpackets, 286fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t *reassembled, size_t *reassembled_len, const char *msg) { 287f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct iphdr *ip = NULL; 288f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct ip6_hdr *ip6 = NULL; 289932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng size_t total_length, pos = 0; 290932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng uint8_t protocol = 0; 291fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t version = ip_version(fragments[0]); 292f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 293f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti for (int i = 0; i < numpackets; i++) { 294fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom const uint8_t *packet = fragments[i]; 295f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int len = lengths[i]; 296f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int headersize, payload_offset; 297f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 298f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(ip_version(packet), version) << msg << ": Inconsistent fragment versions\n"; 299f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(packet, len, "Fragment sanity check"); 300f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 301f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti switch (version) { 302f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case 4: { 303f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct iphdr *ip_orig = (struct iphdr *) packet; 304f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti headersize = sizeof(*ip_orig); 305f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_TRUE(is_ipv4_fragment(ip_orig)) 306f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n"; 307f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip): 0)) 308f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n"; 309f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 310f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti headersize = sizeof(*ip_orig); 311f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti payload_offset = headersize; 312f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (pos == 0) { 313f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip = (struct iphdr *) reassembled; 314f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 315f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 316f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 317f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case 6: { 318f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct ip6_hdr *ip6_orig = (struct ip6_hdr *) packet; 319f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct ip6_frag *frag = (struct ip6_frag *) (ip6_orig + 1); 320f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_TRUE(is_ipv6_fragment(ip6_orig, len)) 321f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n"; 322f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6): 0)) 323f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n"; 324f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 325f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti headersize = sizeof(*ip6_orig); 326f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti payload_offset = sizeof(*ip6_orig) + sizeof(*frag); 327f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (pos == 0) { 328f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6 = (struct ip6_hdr *) reassembled; 329f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti protocol = frag->ip6f_nxt; 330f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 331f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 332f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 333f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti default: 334f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti FAIL() << msg << ": Invalid IP version << " << version; 335f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 336f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 337f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // If this is the first fragment, copy the header. 338f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (pos == 0) { 339f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_LT(headersize, (int) *reassembled_len) << msg << ": Reassembly buffer too small\n"; 340f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti memcpy(reassembled, packet, headersize); 341f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti total_length = headersize; 342f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pos += headersize; 343f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 344f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 345f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Copy the payload. 346f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int payload_length = len - payload_offset; 347f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti total_length += payload_length; 348932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng ASSERT_LT(total_length, *reassembled_len) << msg << ": Reassembly buffer too small\n"; 349f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti memcpy(reassembled + pos, packet + payload_offset, payload_length); 350f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pos += payload_length; 351f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 352f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 353f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 354f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Fix up the reassembled headers to reflect fragmentation and length (and IPv4 checksum). 355f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(total_length, pos) << msg << ": Reassembled packet length incorrect\n"; 356f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (ip) { 357f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip->frag_off &= ~htons(IP_MF); 358f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip->tot_len = htons(total_length); 359f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip->check = 0; 360f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip->check = ip_checksum(ip, sizeof(*ip)); 361f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_FALSE(is_ipv4_fragment(ip)) << msg << ": reassembled IPv4 packet is a fragment!\n"; 362f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 363f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (ip6) { 364f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6->ip6_nxt = protocol; 365f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip6->ip6_plen = htons(total_length - sizeof(*ip6)); 366f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_FALSE(is_ipv6_fragment(ip6, ip6->ip6_plen)) 367f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << msg << ": reassembled IPv6 packet is a fragment!\n"; 368f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 369f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 370f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti *reassembled_len = total_length; 371f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 372f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 373fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_data_matches(const uint8_t *expected, const uint8_t *actual, size_t len, const char *msg) { 374f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (memcmp(expected, actual, len)) { 375f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Hex dump, 20 bytes per line, one space between bytes (1 byte = 3 chars), indented by 4. 376f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int hexdump_len = len * 3 + (len / 20 + 1) * 5; 377f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti char expected_hexdump[hexdump_len], actual_hexdump[hexdump_len]; 378f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti unsigned pos = 0; 379f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti for (unsigned i = 0; i < len; i++) { 380f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (i % 20 == 0) { 381f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti sprintf(expected_hexdump + pos, "\n "); 382f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti sprintf(actual_hexdump + pos, "\n "); 383f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pos += 4; 384f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 385f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti sprintf(expected_hexdump + pos, " %02x", expected[i]); 386f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti sprintf(actual_hexdump + pos, " %02x", actual[i]); 387f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pos += 3; 388f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 389f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti FAIL() << msg << ": Translated packet doesn't match" 390f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "\n Expected:" << (char *) expected_hexdump 391f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "\n Actual:" << (char *) actual_hexdump << "\n"; 392f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 393f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 394f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 395fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid fix_udp_checksum(uint8_t* packet) { 396f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint32_t pseudo_checksum; 397fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t version = ip_version(packet); 398f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct udphdr *udp; 399f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti switch (version) { 400f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case 4: { 401f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct iphdr *ip = (struct iphdr *) packet; 402f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti udp = (struct udphdr *) (ip + 1); 403f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len)); 404f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 405f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 406f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case 6: { 407f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct ip6_hdr *ip6 = (struct ip6_hdr *) packet; 408f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti udp = (struct udphdr *) (ip6 + 1); 409f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP); 410f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 411f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 412f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti default: 413f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti FAIL() << "unsupported IP version" << version << "\n"; 414f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti return; 415f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 416f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 417f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti udp->check = 0; 418f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti udp->check = ip_checksum_finish(ip_checksum_add(pseudo_checksum, udp, ntohs(udp->len))); 419f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 420f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 421fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *out, size_t *outlen, 422f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti const char *msg) { 423f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int fds[2]; 424f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, fds)) { 425f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti abort(); 426f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 427f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct tun_pi tun_header = { 0, 0 }; 428f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 429f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti char foo[512]; 430f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti snprintf(foo, sizeof(foo), "%s: Invalid original packet", msg); 431f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(original, original_len, foo); 432f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 43391d0f1bc6dd24e54ed3caef9b08525b332ab0adfLorenzo Colitti int read_fd, write_fd; 434f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint16_t expected_proto; 435f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int version = ip_version(original); 436f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti switch (version) { 437f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case 4: 438f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti tun_header.proto = htons(ETH_P_IP); 439f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti expected_proto = htons(ETH_P_IPV6); 440f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti read_fd = fds[1]; 44191d0f1bc6dd24e54ed3caef9b08525b332ab0adfLorenzo Colitti write_fd = fds[0]; 442f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 443f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti case 6: 444f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti tun_header.proto = htons(ETH_P_IPV6); 445f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti expected_proto = htons(ETH_P_IP); 446f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti read_fd = fds[0]; 44791d0f1bc6dd24e54ed3caef9b08525b332ab0adfLorenzo Colitti write_fd = fds[1]; 448f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 449f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti default: 450f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti FAIL() << msg << ": Unsupported IP version " << version << "\n"; 451f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti break; 452f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 453f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 45491d0f1bc6dd24e54ed3caef9b08525b332ab0adfLorenzo Colitti translate_packet(write_fd, (version == 4), original, original_len); 455f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 456f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct tun_pi new_tun_header; 457f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct iovec iov[] = { 458f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti { &new_tun_header, sizeof(new_tun_header) }, 459f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti { out, *outlen } 460f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti }; 461f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int len = readv(read_fd, iov, 2); 462f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti if (len > (int) sizeof(new_tun_header)) { 463f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_LT((size_t) len, *outlen) << msg << ": Translated packet buffer too small\n"; 464f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n"; 465f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti *outlen = len - sizeof(new_tun_header); 466f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } else { 467f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti FAIL() << msg << ": Packet was not translated"; 468f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti *outlen = 0; 469f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 470f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 471f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 472fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_translated_packet(const uint8_t *original, size_t original_len, 473fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom const uint8_t *expected, size_t expected_len, const char *msg) { 474fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t translated[MAXMTU]; 475f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti size_t translated_len = sizeof(translated); 476f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti do_translate_packet(original, original_len, translated, &translated_len, msg); 477f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n"; 478f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_data_matches(expected, translated, translated_len, msg); 479f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 480f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 481fcac410fa15613873a07143ccd46470b869346a3Brian Carlstromvoid check_fragment_translation(const uint8_t *original[], const size_t original_lengths[], 482fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom const uint8_t *expected[], const size_t expected_lengths[], 483f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int numfragments, const char *msg) { 484f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti for (int i = 0; i < numfragments; i++) { 485f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Check that each of the fragments translates as expected. 486f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti char frag_msg[512]; 487f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1); 488f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_translated_packet(original[i], original_lengths[i], 489f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti expected[i], expected_lengths[i], frag_msg); 490f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 491f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 492f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Sanity check that reassembling the original and translated fragments produces valid packets. 493fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t reassembled[MAXMTU]; 494f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti size_t reassembled_len = sizeof(reassembled); 495f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg); 496f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(reassembled, reassembled_len, msg); 497f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 498fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t translated[MAXMTU]; 499f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti size_t translated_len = sizeof(translated); 500f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg); 501f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(translated, translated_len, msg); 502f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 503f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 504f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colittistruct clat_config Global_Clatd_Config; 505f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 506f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitticlass ClatdTest : public ::testing::Test { 507f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti protected: 508f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti virtual void SetUp() { 509f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet); 510f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet); 511f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet); 512f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 513f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti}; 514f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 515f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, Sanitycheck) { 516f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Sanity checks the data. 517fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t v4_header[] = { IPV4_UDP_HEADER }; 518f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(sizeof(struct iphdr), sizeof(v4_header)) << "Test IPv4 header: incorrect length\n"; 519f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 520fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t v6_header[] = { IPV6_UDP_HEADER }; 521f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(sizeof(struct ip6_hdr), sizeof(v6_header)) << "Test IPv6 header: incorrect length\n"; 522f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 523fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t udp_header[] = { UDP_HEADER }; 524f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(sizeof(struct udphdr), sizeof(udp_header)) << "Test UDP header: incorrect length\n"; 525f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 526f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Sanity checks check_packet. 527f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct udphdr *udp; 528fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD }; 529f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti udp = (struct udphdr *) (v4_udp_packet + sizeof(struct iphdr)); 530f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti fix_udp_checksum(v4_udp_packet); 531f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n"; 532f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check"); 533f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 534fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD }; 535f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti udp = (struct udphdr *) (v6_udp_packet + sizeof(struct ip6_hdr)); 536f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti fix_udp_checksum(v6_udp_packet); 537f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n"; 538f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check"); 539f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 540fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD }; 541f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(ipv4_ping, sizeof(ipv4_ping), "IPv4 ping sanity check"); 542f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 543fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD }; 544f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check"); 545f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 546f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti // Sanity checks reassemble_packet. 547fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t reassembled[MAXMTU]; 548f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti size_t total_length = sizeof(reassembled); 549f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), 550f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti reassembled, &total_length, "Reassembly sanity check"); 551f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid"); 552f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n"; 553f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *) reassembled)) 554f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "Sanity check: reassembled packet is a fragment!\n"; 555f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check"); 556f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 557f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti total_length = sizeof(reassembled); 558f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments), 559f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti reassembled, &total_length, "IPv6 reassembly sanity check"); 560f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *) reassembled, total_length)) 561f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "Sanity check: reassembled packet is a fragment!\n"; 562f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid"); 563f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 564f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 565f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, PseudoChecksum) { 566f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint32_t pseudo_checksum; 567f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 568fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t v4_header[] = { IPV4_UDP_HEADER }; 569fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) }; 570f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *) v4_header, UDP_LEN); 571f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(ip_checksum_finish(pseudo_checksum), 572f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header))) 573f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "ipv4_pseudo_header_checksum incorrect\n"; 574f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 575fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t v6_header[] = { IPV6_UDP_HEADER }; 576fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) }; 577f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *) v6_header, UDP_LEN, IPPROTO_UDP); 578f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(ip_checksum_finish(pseudo_checksum), 579f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header))) 580f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "ipv6_pseudo_header_checksum incorrect\n"; 581f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 582f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 583f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, TransportChecksum) { 584fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t udphdr[] = { UDP_HEADER }; 585fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t payload[] = { PAYLOAD }; 586f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr))) 587f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "UDP partial checksum\n"; 588f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload))) 589f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "Payload partial checksum\n"; 590f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 591fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t ip[] = { IPV4_UDP_HEADER }; 592fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t ip6[] = { IPV6_UDP_HEADER }; 593f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *) ip, UDP_LEN); 594f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint32_t ipv6_pseudo_sum = ipv6_pseudo_header_checksum((struct ip6_hdr *) ip6, UDP_LEN, 595f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti IPPROTO_UDP); 596f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 597932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum) << "IPv4 pseudo-checksum sanity check\n"; 598932614ee5e740704d7ef951dff6daede4fe12904Ben Cheng EXPECT_EQ(0x2644bU, ipv6_pseudo_sum) << "IPv6 pseudo-checksum sanity check\n"; 599f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ( 600f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti kUdpV4Checksum, 601f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip_checksum_finish(ipv4_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum)) 602f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "Unexpected UDP/IPv4 checksum\n"; 603f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ( 604f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti kUdpV6Checksum, 605f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip_checksum_finish(ipv6_pseudo_sum + kUdpPartialChecksum + kPayloadPartialChecksum)) 606f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "Unexpected UDP/IPv6 checksum\n"; 607f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 608f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(kUdpV6Checksum, 609f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip_checksum_adjust(kUdpV4Checksum, ipv4_pseudo_sum, ipv6_pseudo_sum)) 610f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "Adjust IPv4/UDP checksum to IPv6\n"; 611f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(kUdpV4Checksum, 612f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ip_checksum_adjust(kUdpV6Checksum, ipv6_pseudo_sum, ipv4_pseudo_sum)) 613f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "Adjust IPv6/UDP checksum to IPv4\n"; 614f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 615f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 616f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, AdjustChecksum) { 617f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct checksum_data { 618f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint16_t checksum; 619f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint32_t old_hdr_sum; 620f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint32_t new_hdr_sum; 621f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint16_t result; 622f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } DATA[] = { 623f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti { 0x1423, 0xb8ec, 0x2d757, 0xf5b5 }, 624f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti { 0xf5b5, 0x2d757, 0xb8ec, 0x1423 }, 625f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti { 0xdd2f, 0x5555, 0x3285, 0x0000 }, 626f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti { 0x1215, 0x5560, 0x15560 + 20, 0x1200 }, 627f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti { 0xd0c7, 0x3ad0, 0x2644b, 0xa74a }, 628f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti }; 629f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti unsigned i, failed = 0; 630f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 631f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti for (i = 0; i < ARRAYSIZE(DATA); i++) { 632f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti struct checksum_data *data = DATA + i; 633f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti uint16_t result = ip_checksum_adjust(data->checksum, data->old_hdr_sum, data->new_hdr_sum); 634f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti EXPECT_EQ(result, data->result) 635f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "Incorrect checksum" << std::showbase << std::hex 636f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "\n Expected: " << data->result 637f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "\n Actual: " << result 638f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << "\n checksum=" << data->checksum 639f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti << " old_sum=" << data->old_hdr_sum << " new_sum=" << data->new_hdr_sum << "\n"; 640f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti } 641f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 642f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 643f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, Translate) { 644fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD }; 645fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD }; 646f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti fix_udp_checksum(udp_ipv4); 647f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti fix_udp_checksum(udp_ipv6); 648f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_translated_packet(udp_ipv4, sizeof(udp_ipv4), udp_ipv6, sizeof(udp_ipv6), 649f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti "UDP/IPv4 -> UDP/IPv6 translation"); 650f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_translated_packet(udp_ipv6, sizeof(udp_ipv6), udp_ipv4, sizeof(udp_ipv4), 651f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti "UDP/IPv6 -> UDP/IPv4 translation"); 652f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 653fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t ipv4_ping[] = { IPV4_ICMP_HEADER IPV4_PING PAYLOAD }; 654fcac410fa15613873a07143ccd46470b869346a3Brian Carlstrom uint8_t ipv6_ping[] = { IPV6_ICMPV6_HEADER IPV6_PING PAYLOAD }; 655f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_translated_packet(ipv4_ping, sizeof(ipv4_ping), ipv6_ping, sizeof(ipv6_ping), 656f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti "ICMP->ICMPv6 translation"); 657f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_translated_packet(ipv6_ping, sizeof(ipv6_ping), ipv4_ping, sizeof(ipv4_ping), 658f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti "ICMPv6->ICMP translation"); 659f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 660f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 661f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo ColittiTEST_F(ClatdTest, Fragmentation) { 662f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti int len, i; 663f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_fragment_translation(kIPv4Fragments, kIPv4FragLengths, 664f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti kIPv6Fragments, kIPv6FragLengths, 665f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation"); 666f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti 667f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti check_fragment_translation(kIPv6Fragments, kIPv6FragLengths, 668f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti kIPv4Fragments, kIPv4FragLengths, 669f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation"); 670f3beefc96a5a4f295562f60d648bd6e795980a10Lorenzo Colitti} 671