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 external {@link TestNetworkInterface} to the internal 24 * {@link TestNetworkInterface} with NAT. See {@link NatPacketForwarderBase} for detail. 25 */ 26 class NatExternalPacketForwarder( 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 external 36 * interface. 37 * 38 * Incoming response from external interface which is being forwarded to the internal 39 * interface with translated address, e.g. 1.2.3.4:80 -> 8.8.8.8:1234 40 * will be translated into 8.8.8.8:80 -> 192.168.1.1:5678. 41 * 42 * For packets that are not an incoming response, do not forward them to the 43 * internal interface. 44 */ preparePacketForForwardingnull45 override fun preparePacketForForwarding(buf: ByteArray, len: Int, version: Int, proto: Int) { 46 val (addrPos, addrLen) = getAddressPositionAndLength(version) 47 48 // TODO: support one external address per ip version. 49 val extAddrBuf = mExtAddr.address 50 if (addrLen != extAddrBuf.size) throw IllegalStateException("Packet IP version mismatch") 51 52 // Get internal address by port. 53 val transportOffset = 54 if (version == 4) PacketReflector.IPV4_HEADER_LENGTH 55 else PacketReflector.IPV6_HEADER_LENGTH 56 val dstPort = getPortAt(buf, transportOffset + DESTINATION_PORT_OFFSET) 57 val intAddrInfo = synchronized(mNatMap) { mNatMap.fromExternalPort(dstPort) } 58 // No mapping, skip. This usually happens if the connection is initiated directly on 59 // the external interface, e.g. DNS64 resolution, network validation, etc. 60 if (intAddrInfo == null) return 61 62 val intAddrBuf = intAddrInfo.address.address 63 val intPort = intAddrInfo.port 64 65 // Copy the original destination to into the source address. 66 for (i in 0 until addrLen) { 67 buf[addrPos + i] = buf[addrPos + addrLen + i] 68 } 69 70 // Copy the internal address into the destination address. 71 for (i in 0 until addrLen) { 72 buf[addrPos + addrLen + i] = intAddrBuf[i] 73 } 74 75 // Copy the internal port into the destination port. 76 setPortAt(intPort, buf, transportOffset + DESTINATION_PORT_OFFSET) 77 78 // Fix IP and Transport layer checksum. 79 fixPacketChecksum(buf, len, version, proto.toByte()) 80 } 81 } 82