• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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