You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.9 KiB
106 lines
3.9 KiB
/*
|
|
* Copyright (C) 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <map>
|
|
#include <thread>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <android-base/result.h>
|
|
#include <android-base/unique_fd.h>
|
|
#include <netdutils/Slice.h>
|
|
|
|
namespace android::net {
|
|
|
|
// Given a TUN interface fd, TunForwarder reads packets from the fd, changes their IP header
|
|
// according to a set of forwarding rules (which can be set by addForwardingRule), and sends
|
|
// new packets back to the fd. Only IPv4 and IPv6 packets with recognized source and destination
|
|
// addresses are accepted; other packets are silently ignored.
|
|
class TunForwarder {
|
|
public:
|
|
TunForwarder(base::unique_fd tunFd);
|
|
~TunForwarder();
|
|
|
|
bool addForwardingRule(const std::array<std::string, 2>& from,
|
|
const std::array<std::string, 2>& to);
|
|
bool startForwarding();
|
|
bool stopForwarding();
|
|
|
|
static base::unique_fd createTun(const std::string& ifname);
|
|
|
|
private:
|
|
// TODO: Considering using IPAddress for v4pair and v6pair. This might requires adding
|
|
// addr4() and addr6() as IPPrefix does.
|
|
struct v4pair {
|
|
static base::Result<v4pair> makePair(const std::array<std::string, 2>& addrs);
|
|
v4pair() = default;
|
|
v4pair(int32_t srcAddr, int32_t dstAddr) {
|
|
src.s_addr = static_cast<in_addr_t>(srcAddr);
|
|
dst.s_addr = static_cast<in_addr_t>(dstAddr);
|
|
}
|
|
in_addr src;
|
|
in_addr dst;
|
|
bool operator==(const v4pair& o) const;
|
|
bool operator<(const v4pair& o) const;
|
|
};
|
|
|
|
struct v6pair {
|
|
static base::Result<v6pair> makePair(const std::array<std::string, 2>& addrs);
|
|
v6pair() = default;
|
|
v6pair(const in6_addr& srcAddr, const in6_addr& dstAddr) : src(srcAddr), dst(dstAddr) {}
|
|
in6_addr src;
|
|
in6_addr dst;
|
|
bool operator==(const v6pair& o) const;
|
|
bool operator<(const v6pair& o) const;
|
|
};
|
|
|
|
void loop();
|
|
void handlePacket(int fd) const;
|
|
|
|
// Send a signal to terminate the loop thread.
|
|
bool signalEventFd();
|
|
|
|
// A series of functions to check the packet. Return error if the packet is neither UDP nor TCP.
|
|
base::Result<void> validatePacket(netdutils::Slice tunPacket) const;
|
|
base::Result<void> validateIpv4Packet(netdutils::Slice ipv4Packet) const;
|
|
base::Result<void> validateIpv6Packet(netdutils::Slice ipv6Packet) const;
|
|
base::Result<void> validateUdpPacket(netdutils::Slice udpPacket) const;
|
|
base::Result<void> validateTcpPacket(netdutils::Slice tcpPacket) const;
|
|
|
|
// The function assumes |tunPacket| is either UDP or TCP packet, changes the source/destination
|
|
// addresses, and updates the checksum.
|
|
base::Result<void> translatePacket(netdutils::Slice tunPacket) const;
|
|
base::Result<void> translateIpv4Packet(netdutils::Slice ipv4Packet) const;
|
|
base::Result<void> translateIpv6Packet(netdutils::Slice ipv6Packet) const;
|
|
void translateUdpPacket(netdutils::Slice udpPacket, uint32_t oldPseudoSum,
|
|
uint32_t newPseudoSum) const;
|
|
void translateTcpPacket(netdutils::Slice tcpPacket, uint32_t oldPseudoSum,
|
|
uint32_t newPseudoSum) const;
|
|
|
|
std::thread mForwarder;
|
|
base::unique_fd mTunFd;
|
|
base::unique_fd mEventFd;
|
|
std::map<v4pair, v4pair> mRulesIpv4;
|
|
std::map<v6pair, v6pair> mRulesIpv6;
|
|
|
|
static constexpr int kPollTimeoutMs = 5000;
|
|
};
|
|
|
|
} // namespace android::net
|