1 /* 2 * Copyright (C) 2023 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 com.android.testutils 18 19 import java.io.FileDescriptor 20 import java.net.InetAddress 21 22 /** 23 * A class that forwards packets from the internal {@link TestNetworkInterface} to the external 24 * {@link TestNetworkInterface} with NAT. See {@link NatPacketForwarderBase} for detail. 25 */ 26 class NatInternalPacketForwarder( 27 srcFd: FileDescriptor, 28 mtu: Int, 29 dstFd: FileDescriptor, 30 extAddr: InetAddress, 31 natMap: PacketBridge.NatMap 32 ) : NatPacketForwarderBase(srcFd, mtu, dstFd, extAddr, natMap) { 33 34 /** 35 * Rewrite addresses, ports and fix up checksums for packets received on the internal 36 * interface. 37 * 38 * Outgoing packet from the internal interface which is being forwarded to the 39 * external interface with translated address, e.g. 192.168.1.1:5678 -> 8.8.8.8:80 40 * will be translated into 8.8.8.8:1234 -> 1.2.3.4:80. 41 * 42 * The external port, e.g. 1234 in the above example, is the port number assigned by 43 * the forwarder when creating the mapping to identify the source address and port when 44 * the response is coming from the external interface. See {@link PacketBridge.NatMap} 45 * for detail. 46 */ preparePacketForForwardingnull47 override fun preparePacketForForwarding(buf: ByteArray, len: Int, version: Int, proto: Int) { 48 val (addrPos, addrLen) = getAddressPositionAndLength(version) 49 50 // TODO: support one external address per ip version. 51 val extAddrBuf = mExtAddr.address 52 if (addrLen != extAddrBuf.size) throw IllegalStateException("Packet IP version mismatch") 53 54 val srcAddr = getInetAddressAt(buf, addrPos, addrLen) 55 56 // Copy the original destination to into the source address. 57 for (i in 0 until addrLen) { 58 buf[addrPos + i] = buf[addrPos + addrLen + i] 59 } 60 61 // Copy the external address into the destination address. 62 for (i in 0 until addrLen) { 63 buf[addrPos + addrLen + i] = extAddrBuf[i] 64 } 65 66 // Add an entry to NAT mapping table. 67 val transportOffset = 68 if (version == 4) PacketReflector.IPV4_HEADER_LENGTH 69 else PacketReflector.IPV6_HEADER_LENGTH 70 val srcPort = getPortAt(buf, transportOffset) 71 val extPort = synchronized(mNatMap) { mNatMap.toExternalPort(srcAddr, srcPort, proto) } 72 // Copy the external port to into the source port. 73 setPortAt(extPort, buf, transportOffset) 74 75 // Fix IP and Transport layer checksum. 76 fixPacketChecksum(buf, len, version, proto.toByte()) 77 } 78 } 79