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 17package android.net.util; 18 19import android.net.util.IpUtils; 20import android.test.suitebuilder.annotation.SmallTest; 21 22import java.nio.ByteBuffer; 23 24import junit.framework.TestCase; 25 26 27public class IpUtilsTest extends TestCase { 28 29 private static final int IPV4_HEADER_LENGTH = 20; 30 private static final int IPV6_HEADER_LENGTH = 40; 31 private static final int TCP_HEADER_LENGTH = 20; 32 private static final int UDP_HEADER_LENGTH = 8; 33 private static final int IP_CHECKSUM_OFFSET = 10; 34 private static final int TCP_CHECKSUM_OFFSET = 16; 35 private static final int UDP_CHECKSUM_OFFSET = 6; 36 37 private int getUnsignedByte(ByteBuffer buf, int offset) { 38 return buf.get(offset) & 0xff; 39 } 40 41 private int getChecksum(ByteBuffer buf, int offset) { 42 return getUnsignedByte(buf, offset) * 256 + getUnsignedByte(buf, offset + 1); 43 } 44 45 private void assertChecksumEquals(int expected, short actual) { 46 assertEquals(Integer.toHexString(expected), Integer.toHexString(actual & 0xffff)); 47 } 48 49 // Generate test packets using Python code like this:: 50 // 51 // from scapy import all as scapy 52 // 53 // def JavaPacketDefinition(bytes): 54 // out = " ByteBuffer packet = ByteBuffer.wrap(new byte[] {\n " 55 // for i in xrange(len(bytes)): 56 // out += "(byte) 0x%02x" % ord(bytes[i]) 57 // if i < len(bytes) - 1: 58 // if i % 4 == 3: 59 // out += ",\n " 60 // else: 61 // out += ", " 62 // out += "\n });" 63 // return out 64 // 65 // packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2") / 66 // scapy.UDP(sport=12345, dport=7) / 67 // "hello") 68 // print JavaPacketDefinition(str(packet)) 69 70 @SmallTest 71 public void testIpv6TcpChecksum() throws Exception { 72 // packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80) / 73 // scapy.TCP(sport=12345, dport=7, 74 // seq=1692871236, ack=128376451, flags=16, 75 // window=32768) / 76 // "hello, world") 77 ByteBuffer packet = ByteBuffer.wrap(new byte[] { 78 (byte) 0x68, (byte) 0x00, (byte) 0x00, (byte) 0x00, 79 (byte) 0x00, (byte) 0x20, (byte) 0x06, (byte) 0x40, 80 (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, 81 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 82 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 83 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, 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) 0x02, 88 (byte) 0x30, (byte) 0x39, (byte) 0x00, (byte) 0x07, 89 (byte) 0x64, (byte) 0xe7, (byte) 0x2a, (byte) 0x44, 90 (byte) 0x07, (byte) 0xa6, (byte) 0xde, (byte) 0x83, 91 (byte) 0x50, (byte) 0x10, (byte) 0x80, (byte) 0x00, 92 (byte) 0xee, (byte) 0x71, (byte) 0x00, (byte) 0x00, 93 (byte) 0x68, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, 94 (byte) 0x6f, (byte) 0x2c, (byte) 0x20, (byte) 0x77, 95 (byte) 0x6f, (byte) 0x72, (byte) 0x6c, (byte) 0x64 96 }); 97 98 // Check that a valid packet has checksum 0. 99 int transportLen = packet.limit() - IPV6_HEADER_LENGTH; 100 assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen)); 101 102 // Check that we can calculate the checksum from scratch. 103 int sumOffset = IPV6_HEADER_LENGTH + TCP_CHECKSUM_OFFSET; 104 int sum = getUnsignedByte(packet, sumOffset) * 256 + getUnsignedByte(packet, sumOffset + 1); 105 assertEquals(0xee71, sum); 106 107 packet.put(sumOffset, (byte) 0); 108 packet.put(sumOffset + 1, (byte) 0); 109 assertChecksumEquals(sum, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen)); 110 111 // Check that writing the checksum back into the packet results in a valid packet. 112 packet.putShort( 113 sumOffset, 114 IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen)); 115 assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen)); 116 } 117 118 @SmallTest 119 public void testIpv4UdpChecksum() { 120 // packet = (scapy.IP(src="192.0.2.1", dst="192.0.2.2", tos=0x40) / 121 // scapy.UDP(sport=32012, dport=4500) / 122 // "\xff") 123 ByteBuffer packet = ByteBuffer.wrap(new byte[] { 124 (byte) 0x45, (byte) 0x40, (byte) 0x00, (byte) 0x1d, 125 (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, 126 (byte) 0x40, (byte) 0x11, (byte) 0xf6, (byte) 0x8b, 127 (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01, 128 (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x02, 129 (byte) 0x7d, (byte) 0x0c, (byte) 0x11, (byte) 0x94, 130 (byte) 0x00, (byte) 0x09, (byte) 0xee, (byte) 0x36, 131 (byte) 0xff 132 }); 133 134 // Check that a valid packet has IP checksum 0 and UDP checksum 0xffff (0 is not a valid 135 // UDP checksum, so the udpChecksum rewrites 0 to 0xffff). 136 assertEquals(0, IpUtils.ipChecksum(packet, 0)); 137 assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH)); 138 139 // Check that we can calculate the checksums from scratch. 140 final int ipSumOffset = IP_CHECKSUM_OFFSET; 141 final int ipSum = getChecksum(packet, ipSumOffset); 142 assertEquals(0xf68b, ipSum); 143 144 packet.put(ipSumOffset, (byte) 0); 145 packet.put(ipSumOffset + 1, (byte) 0); 146 assertChecksumEquals(ipSum, IpUtils.ipChecksum(packet, 0)); 147 148 final int udpSumOffset = IPV4_HEADER_LENGTH + UDP_CHECKSUM_OFFSET; 149 final int udpSum = getChecksum(packet, udpSumOffset); 150 assertEquals(0xee36, udpSum); 151 152 packet.put(udpSumOffset, (byte) 0); 153 packet.put(udpSumOffset + 1, (byte) 0); 154 assertChecksumEquals(udpSum, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH)); 155 156 // Check that writing the checksums back into the packet results in a valid packet. 157 packet.putShort(ipSumOffset, IpUtils.ipChecksum(packet, 0)); 158 packet.putShort(udpSumOffset, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH)); 159 assertEquals(0, IpUtils.ipChecksum(packet, 0)); 160 assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH)); 161 } 162} 163