0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 20:13:05 +02:00

vpnservpool : major refactor for OMI.

* eliminated the GENERAL_POOL enumeration and vector.

* added support for standalone "ifconfig-push" directive
  as alternative to "server" for OMI agents that
  manage their own IP address pools.
This commit is contained in:
James Yonan 2016-05-05 00:37:10 -06:00
parent a2fe68ae68
commit cd1a20964b
2 changed files with 63 additions and 142 deletions

View File

@ -157,13 +157,6 @@ namespace openvpn {
}
}
static bool configured(const OptionList& opt,
const std::string& opt_name,
const bool ipv4_optional)
{
return !ipv4_optional || opt.exists(opt_name) || opt.exists(opt_name + "-ipv6");
}
const Netblock& netblock4() const { return snb4; }
const Netblock& netblock6() const { return snb6; }

View File

@ -42,64 +42,8 @@ namespace openvpn {
OPENVPN_EXCEPTION(vpn_serv_pool_error);
class Set;
class IP46;
enum Index {
GENERAL_POOL=0,
//OTHER_POOL,
SIZE
};
inline const char *pool_name(const unsigned int i)
struct IP46
{
static const char *const names[] = {
"server",
//"other-pool",
};
static_assert(SIZE == array_size(names), "VPNServerPool::pool_name() size inconsistency");
if (i < SIZE)
return names[i];
else
return "UNDEF_POOL";
}
class Pool : public VPNServerNetblock
{
public:
friend IP46;
Pool(const OptionList& opt,
const std::string& opt_name,
const bool ipv4_optional)
: VPNServerNetblock(opt, opt_name, ipv4_optional, 0)
{
pool4.add_range(netblock4().clients);
pool6.add_range(netblock6().clients);
}
private:
IP::Pool pool4;
IP::Pool pool6;
};
class IP46
{
public:
friend Set;
enum Flags {
IPv4_DEPLETION=(1<<0),
IPv6_DEPLETION=(1<<1),
};
IP46()
: pool_index(-1)
{}
void add_routes(std::vector<IP::Route>& rtvec,
const std::uint32_t mark)
{
@ -109,11 +53,6 @@ namespace openvpn {
rtvec.emplace_back(ip6, ip6.size(), mark);
}
bool defined() const
{
return pool_index >= 0 && pool_index < SIZE;
}
std::string to_string() const
{
std::ostringstream os;
@ -121,91 +60,78 @@ namespace openvpn {
return os.str();
}
bool defined() const
{
return ip4.defined() || ip6.defined();
}
IP::Addr ip4;
IP::Addr ip6;
};
private:
// returns flags
unsigned int acquire(Pool& pool, const unsigned int index, const bool request_ipv6)
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))
{
unsigned int flags = 0;
pool_index = index;
if (!pool.pool4.acquire_addr(ip4))
flags |= IPv4_DEPLETION;
if (request_ipv6 && pool.netblock6().defined())
if (configured(opt, "server"))
{
if (!pool.pool6.acquire_addr(ip6))
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(Pool& pool)
{
if (ip4.defined())
pool.pool4.release_addr(ip4);
if (ip6.defined())
pool.pool6.release_addr(ip6);
pool_index = -1;
}
int pool_index;
};
class Set
{
public:
Set(const OptionList& opt)
{
for (unsigned int i = 0; i < SIZE; ++i)
{
const std::string opt_name = pool_name(i);
const bool ipv4_optional = (i > 0);
if (VPNServerNetblock::configured(opt, opt_name, ipv4_optional))
pools.emplace_back(new Pool(opt, opt_name, ipv4_optional));
else
pools.emplace_back();
}
}
// returns IP46::Flags
unsigned int acquire(IP46& ip46, const unsigned int index, const bool request_ipv6)
void release(IP46& addr_pair)
{
std::lock_guard<std::mutex> lock(mutex);
if (index >= SIZE)
OPENVPN_THROW(vpn_serv_pool_error, "pool index=" << index << " is out of range (must be less than " << SIZE << ')');
if (!pools[index])
OPENVPN_THROW(vpn_serv_pool_error, pool_name(index) << " IP address pool is undefined");
return ip46.acquire(*pools[index], index, request_ipv6);
}
void release(IP46& ip46)
{
std::lock_guard<std::mutex> lock(mutex);
if (!ip46.defined())
return;
if (!pools[ip46.pool_index])
return;
ip46.release(*pools[ip46.pool_index]);
}
const VPNServerNetblock* snb(const IP46& ip46)
{
if (!ip46.defined())
return nullptr;
return pools[ip46.pool_index].get();
}
const VPNServerNetblock* snb(const unsigned int index)
{
if (index >= SIZE)
return nullptr;
return pools[index].get();
if (addr_pair.ip4.defined())
pool4.release_addr(addr_pair.ip4);
if (addr_pair.ip6.defined())
pool6.release_addr(addr_pair.ip6);
}
private:
std::vector<std::unique_ptr<Pool>> pools; // size is always SIZE after construction
static VPNServerNetblock init_snb_from_opt(const OptionList& opt)
{
if (configured(opt, "server"))
return VPNServerNetblock(opt, "server", false, 0);
else if (configured(opt, "ifconfig"))
return VPNServerNetblock(opt, "ifconfig", false, 0);
else
throw vpn_serv_pool_error("one of 'server' or 'ifconfig' directives is required");
}
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>
@ -213,19 +139,21 @@ namespace openvpn {
public:
typedef RCPtr<IP46AutoRelease> Ptr;
IP46AutoRelease(Set& set_arg)
: set(set_arg)
IP46AutoRelease(Pool* pool_arg)
: pool(pool_arg)
{
}
~IP46AutoRelease()
{
set.release(*this);
if (pool)
pool->release(*this);
}
private:
Set& set;
Pool* pool;
};
}
}