1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012- OpenVPN Inc.
//
// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//
#ifndef OPENVPN_SERVER_VPNSERVPOOL_H
#define OPENVPN_SERVER_VPNSERVPOOL_H
#include <memory>
#include <mutex>
#include <sstream>
#include <vector>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/rc.hpp>
#include <openvpn/server/vpnservnetblock.hpp>
#include <openvpn/addr/ip.hpp>
#include <openvpn/addr/route.hpp>
#include <openvpn/addr/pool.hpp>
namespace openvpn::VPNServerPool {
OPENVPN_EXCEPTION(vpn_serv_pool_error);
struct IP46
{
void add_routes(std::vector<IP::Route> &rtvec)
{
if (ip4.defined())
rtvec.emplace_back(ip4, ip4.size());
if (ip6.defined())
rtvec.emplace_back(ip6, ip6.size());
}
std::string to_string() const
{
std::ostringstream os;
os << '[' << ip4 << ' ' << ip6 << ']';
return os.str();
}
bool defined() const
{
return ip4.defined() || ip6.defined();
}
IP::Addr ip4;
IP::Addr ip6;
};
class Pool : public VPNServerNetblock
{
public:
enum Flags
{
IPv4_DEPLETION = (1 << 0),
IPv6_DEPLETION = (1 << 1),
};
Pool(const OptionList &opt)
: VPNServerNetblock(init_snb_from_opt(opt))
{
if (configured(opt, "server"))
{
pool4.add_range(netblock4().clients);
pool6.add_range(netblock6().clients);
}
}
// returns flags
unsigned int acquire(IP46 &addr_pair, const bool request_ipv6)
{
std::lock_guard<std::mutex> lock(mutex);
unsigned int flags = 0;
if (!pool4.acquire_addr(addr_pair.ip4))
flags |= IPv4_DEPLETION;
if (request_ipv6 && netblock6().defined())
{
if (!pool6.acquire_addr(addr_pair.ip6))
flags |= IPv6_DEPLETION;
}
return flags;
}
void release(IP46 &addr_pair)
{
std::lock_guard<std::mutex> lock(mutex);
if (addr_pair.ip4.defined())
pool4.release_addr(addr_pair.ip4);
if (addr_pair.ip6.defined())
pool6.release_addr(addr_pair.ip6);
}
private:
static VPNServerNetblock init_snb_from_opt(const OptionList &opt)
{
if (configured(opt, "server"))
return VPNServerNetblock(opt, "server", false, 0);
if (configured(opt, "ifconfig"))
return VPNServerNetblock(opt, "ifconfig", false, 0);
return VPNServerNetblock();
}
static bool configured(const OptionList &opt,
const std::string &opt_name)
{
return opt.exists(opt_name) || opt.exists(opt_name + "-ipv6");
}
std::mutex mutex;
IP::Pool pool4;
IP::Pool pool6;
};
class IP46AutoRelease : public IP46, public RC<thread_safe_refcount>
{
public:
typedef RCPtr<IP46AutoRelease> Ptr;
IP46AutoRelease(Pool *pool_arg)
: pool(pool_arg)
{
}
~IP46AutoRelease()
{
if (pool)
pool->release(*this);
}
private:
Pool *pool;
};
} // namespace openvpn::VPNServerPool
#endif
|