1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.util; 18 19 import static org.junit.Assert.assertEquals; 20 21 import android.support.test.runner.AndroidJUnit4; 22 import android.support.test.filters.SmallTest; 23 24 import java.nio.ByteBuffer; 25 26 import org.junit.runner.RunWith; 27 import org.junit.Test; 28 29 @RunWith(AndroidJUnit4.class) 30 @SmallTest 31 public class IpUtilsTest { 32 33 private static final int IPV4_HEADER_LENGTH = 20; 34 private static final int IPV6_HEADER_LENGTH = 40; 35 private static final int TCP_HEADER_LENGTH = 20; 36 private static final int UDP_HEADER_LENGTH = 8; 37 private static final int IP_CHECKSUM_OFFSET = 10; 38 private static final int TCP_CHECKSUM_OFFSET = 16; 39 private static final int UDP_CHECKSUM_OFFSET = 6; 40 41 private int getUnsignedByte(ByteBuffer buf, int offset) { 42 return buf.get(offset) & 0xff; 43 } 44 45 private int getChecksum(ByteBuffer buf, int offset) { 46 return getUnsignedByte(buf, offset) * 256 + getUnsignedByte(buf, offset + 1); 47 } 48 49 private void assertChecksumEquals(int expected, short actual) { 50 assertEquals(Integer.toHexString(expected), Integer.toHexString(actual & 0xffff)); 51 } 52 53 // Generate test packets using Python code like this:: 54 // 55 // from scapy import all as scapy 56 // 57 // def JavaPacketDefinition(bytes): 58 // out = " ByteBuffer packet = ByteBuffer.wrap(new byte[] {\n " 59 // for i in xrange(len(bytes)): 60 // out += "(byte) 0x%02x" % ord(bytes[i]) 61 // if i < len(bytes) - 1: 62 // if i % 4 == 3: 63 // out += ",\n " 64 // else: 65 // out += ", " 66 // out += "\n });" 67 // return out 68 // 69 // packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2") / 70 // scapy.UDP(sport=12345, dport=7) / 71 // "hello") 72 // print JavaPacketDefinition(str(packet)) 73 74 @Test 75 public void testIpv6TcpChecksum() throws Exception { 76 // packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80) / 77 // scapy.TCP(sport=12345, dport=7, 78 // seq=1692871236, ack=128376451, flags=16, 79 // window=32768) / 80 // "hello, world") 81 ByteBuffer packet = ByteBuffer.wrap(new byte[] { 82 (byte) 0x68, (byte) 0x00, (byte) 0x00, (byte) 0x00, 83 (byte) 0x00, (byte) 0x20, (byte) 0x06, (byte) 0x40, 84 (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, 85 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 86 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 87 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, 88 (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, 89 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 90 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 91 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, 92 (byte) 0x30, (byte) 0x39, (byte) 0x00, (byte) 0x07, 93 (byte) 0x64, (byte) 0xe7, (byte) 0x2a, (byte) 0x44, 94 (byte) 0x07, (byte) 0xa6, (byte) 0xde, (byte) 0x83, 95 (byte) 0x50, (byte) 0x10, (byte) 0x80, (byte) 0x00, 96 (byte) 0xee, (byte) 0x71, (byte) 0x00, (byte) 0x00, 97 (byte) 0x68, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, 98 (byte) 0x6f, (byte) 0x2c, (byte) 0x20, (byte) 0x77, 99 (byte) 0x6f, (byte) 0x72, (byte) 0x6c, (byte) 0x64 100 }); 101 102 // Check that a valid packet has checksum 0. 103 int transportLen = packet.limit() - IPV6_HEADER_LENGTH; 104 assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen)); 105 106 // Check that we can calculate the checksum from scratch. 107 int sumOffset = IPV6_HEADER_LENGTH + TCP_CHECKSUM_OFFSET; 108 int sum = getUnsignedByte(packet, sumOffset) * 256 + getUnsignedByte(packet, sumOffset + 1); 109 assertEquals(0xee71, sum); 110 111 packet.put(sumOffset, (byte) 0); 112 packet.put(sumOffset + 1, (byte) 0); 113 assertChecksumEquals(sum, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen)); 114 115 // Check that writing the checksum back into the packet results in a valid packet. 116 packet.putShort( 117 sumOffset, 118 IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen)); 119 assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen)); 120 } 121 122 @Test 123 public void testIpv4UdpChecksum() { 124 // packet = (scapy.IP(src="192.0.2.1", dst="192.0.2.2", tos=0x40) / 125 // scapy.UDP(sport=32012, dport=4500) / 126 // "\xff") 127 ByteBuffer packet = ByteBuffer.wrap(new byte[] { 128 (byte) 0x45, (byte) 0x40, (byte) 0x00, (byte) 0x1d, 129 (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, 130 (byte) 0x40, (byte) 0x11, (byte) 0xf6, (byte) 0x8b, 131 (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01, 132 (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x02, 133 (byte) 0x7d, (byte) 0x0c, (byte) 0x11, (byte) 0x94, 134 (byte) 0x00, (byte) 0x09, (byte) 0xee, (byte) 0x36, 135 (byte) 0xff 136 }); 137 138 // Check that a valid packet has IP checksum 0 and UDP checksum 0xffff (0 is not a valid 139 // UDP checksum, so the udpChecksum rewrites 0 to 0xffff). 140 assertEquals(0, IpUtils.ipChecksum(packet, 0)); 141 assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH)); 142 143 // Check that we can calculate the checksums from scratch. 144 final int ipSumOffset = IP_CHECKSUM_OFFSET; 145 final int ipSum = getChecksum(packet, ipSumOffset); 146 assertEquals(0xf68b, ipSum); 147 148 packet.put(ipSumOffset, (byte) 0); 149 packet.put(ipSumOffset + 1, (byte) 0); 150 assertChecksumEquals(ipSum, IpUtils.ipChecksum(packet, 0)); 151 152 final int udpSumOffset = IPV4_HEADER_LENGTH + UDP_CHECKSUM_OFFSET; 153 final int udpSum = getChecksum(packet, udpSumOffset); 154 assertEquals(0xee36, udpSum); 155 156 packet.put(udpSumOffset, (byte) 0); 157 packet.put(udpSumOffset + 1, (byte) 0); 158 assertChecksumEquals(udpSum, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH)); 159 160 // Check that writing the checksums back into the packet results in a valid packet. 161 packet.putShort(ipSumOffset, IpUtils.ipChecksum(packet, 0)); 162 packet.putShort(udpSumOffset, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH)); 163 assertEquals(0, IpUtils.ipChecksum(packet, 0)); 164 assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH)); 165 } 166 } 167