Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'

This commit is contained in:
Sergey Abramchuk
2020-02-24 14:43:11 +03:00
655 changed files with 146468 additions and 0 deletions
@@ -0,0 +1,119 @@
// 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-2017 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Handle ACK tracking for reliability layer
#ifndef OPENVPN_RELIABLE_RELACK_H
#define OPENVPN_RELIABLE_RELACK_H
#include <deque>
#include <algorithm>
#include <limits>
#include <openvpn/common/socktypes.hpp>
#include <openvpn/buffer/buffer.hpp>
#include <openvpn/crypto/packet_id.hpp>
#include <openvpn/reliable/relcommon.hpp>
namespace openvpn {
class ReliableAck
{
public:
typedef reliable::id_t id_t;
ReliableAck(const size_t max_ack_list)
: max_ack_list_(max_ack_list ? max_ack_list : std::numeric_limits<size_t>::max()) {}
size_t size() const { return data.size(); }
bool empty() const { return data.empty(); }
void push_back(id_t value) { data.push_back(value); }
id_t front() const { return data.front(); }
void pop_front() { data.pop_front(); }
// Called to read incoming ACK IDs from buf and mark them as ACKed in rel_send.
// If live is false, read the ACK IDs, but don't modify rel_send.
// Return the number of ACK IDs read.
template <typename REL_SEND>
static size_t ack(REL_SEND& rel_send, Buffer& buf, const bool live)
{
const size_t len = buf.pop_front();
for (size_t i = 0; i < len; ++i)
{
const id_t id = read_id(buf);
if (live)
rel_send.ack(id);
}
return len;
}
static size_t ack_skip(Buffer& buf)
{
const size_t len = buf.pop_front();
for (size_t i = 0; i < len; ++i)
read_id(buf);
return len;
}
// copy ACKs from buffer to self
void read(Buffer& buf)
{
const size_t len = buf.pop_front();
for (size_t i = 0; i < len; ++i)
{
const id_t id = read_id(buf);
data.push_back(id);
}
}
// called to write outgoing ACKs to buf
void prepend(Buffer& buf)
{
const size_t len = std::min(data.size(), max_ack_list_);
for (size_t i = len; i > 0; --i)
{
prepend_id(buf, data[i-1]);
}
buf.push_front((unsigned char)len);
data.erase (data.begin(), data.begin()+len);
}
static void prepend_id(Buffer& buf, const id_t id)
{
const id_t net_id = htonl(id);
buf.prepend ((unsigned char *)&net_id, sizeof (net_id));
}
static id_t read_id(Buffer& buf)
{
id_t net_id;
buf.read ((unsigned char *)&net_id, sizeof (net_id));
return ntohl(net_id);
}
private:
size_t max_ack_list_; // Maximum number of ACKs placed in a single message by prepend_acklist()
std::deque<id_t> data;
};
} // namespace openvpn
#endif // OPENVPN_RELIABLE_RELACK_H
@@ -0,0 +1,63 @@
// 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-2017 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Common reliability layer classes
#ifndef OPENVPN_RELIABLE_RELCOMMON_H
#define OPENVPN_RELIABLE_RELCOMMON_H
#include <openvpn/crypto/packet_id.hpp>
namespace openvpn {
namespace reliable {
typedef PacketID::id_t id_t;
}
template <typename PACKET>
class ReliableMessageBase
{
public:
typedef reliable::id_t id_t;
ReliableMessageBase() : id_(0), erased_(false) {}
bool defined() const { return bool(packet); }
bool erased() const { return erased_; }
void erase()
{
id_ = id_t(0);
packet.reset();
erased_ = true;
}
id_t id() const { return id_; }
PACKET packet;
protected:
id_t id_;
bool erased_;
};
} // namespace openvpn
#endif // OPENVPN_RELIABLE_RELCOMMON_H
@@ -0,0 +1,97 @@
// 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-2017 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Receiver side of reliability layer
#ifndef OPENVPN_RELIABLE_RELRECV_H
#define OPENVPN_RELIABLE_RELRECV_H
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/msgwin.hpp>
#include <openvpn/reliable/relcommon.hpp>
namespace openvpn {
template <typename PACKET>
class ReliableRecvTemplate
{
public:
OPENVPN_SIMPLE_EXCEPTION(rel_next_sequenced_not_ready);
typedef reliable::id_t id_t;
class Message : public ReliableMessageBase<PACKET>
{
friend class ReliableRecvTemplate;
};
ReliableRecvTemplate() {}
ReliableRecvTemplate(const id_t span) { init(span); }
void init(const id_t span)
{
window_.init(0, span);
}
// Call with unsequenced packet off of the wire.
// Will return receive flags below.
enum {
ACK_TO_SENDER = (1<<0), // ACK for this packet should be returned to sender
IN_WINDOW = (1<<1) // Packet is in-window (otherwise, packet is dropped)
};
unsigned int receive(const PACKET& packet, const id_t id)
{
if (window_.in_window(id))
{
Message& m = window_.ref_by_id(id);
m.id_ = id;
m.packet = packet;
return ACK_TO_SENDER|IN_WINDOW;
}
else
return window_.pre_window(id) ? ACK_TO_SENDER : 0;
}
// Return true if next_sequenced() is ready to return next message
bool ready() const { return window_.head_defined(); }
// Return next message in sequence.
// Requires that ready() returns true.
Message& next_sequenced()
{
return window_.ref_head();
}
// Call after message returned by receive is ready to
// be disposed of.
void advance()
{
window_.rm_head_nocheck();
}
private:
MessageWindow<Message, id_t> window_;
};
} // namespace openvpn
#endif // OPENVPN_RELIABLE_RELRECV_H
@@ -0,0 +1,148 @@
// 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-2017 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Sender side of reliability layer
#ifndef OPENVPN_RELIABLE_RELSEND_H
#define OPENVPN_RELIABLE_RELSEND_H
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/msgwin.hpp>
#include <openvpn/time/time.hpp>
#include <openvpn/reliable/relcommon.hpp>
namespace openvpn {
template <typename PACKET>
class ReliableSendTemplate
{
public:
typedef reliable::id_t id_t;
class Message : public ReliableMessageBase<PACKET>
{
friend class ReliableSendTemplate;
using ReliableMessageBase<PACKET>::defined;
public:
bool ready_retransmit(const Time& now) const
{
return defined() && now >= retransmit_at_;
}
Time::Duration until_retransmit(const Time& now) const
{
Time::Duration ret;
if (now < retransmit_at_)
ret = retransmit_at_ - now;
return ret;
}
void reset_retransmit(const Time& now, const Time::Duration& tls_timeout)
{
retransmit_at_ = now + tls_timeout;
}
private:
Time retransmit_at_;
};
ReliableSendTemplate() : next(0) {}
ReliableSendTemplate(const id_t span) { init(span); }
void init(const id_t span)
{
next = 0;
window_.init(next, span);
}
// Return the id that the object at the head of the queue
// would have (even if it isn't defined yet).
id_t head_id() const { return window_.head_id(); }
// Return the ID of one past the end of the window
id_t tail_id() const { return window_.tail_id(); }
// Return the window size
id_t span() const { return window_.span(); }
// Return a reference to M object at id, throw exception
// if id is not in current window
Message& ref_by_id(const id_t id)
{
return window_.ref_by_id(id);
}
// Return the shortest duration for any pending retransmissions
Time::Duration until_retransmit(const Time& now)
{
Time::Duration ret = Time::Duration::infinite();
for (id_t i = head_id(); i < tail_id(); ++i)
{
const Message& msg = ref_by_id(i);
if (msg.defined())
{
Time::Duration ut = msg.until_retransmit(now);
if (ut < ret)
ret = ut;
}
}
return ret;
}
// Return number of unacknowleged packets in send queue
unsigned int n_unacked()
{
unsigned int ret = 0;
for (id_t i = head_id(); i < tail_id(); ++i)
{
if (ref_by_id(i).defined())
++ret;
}
return ret;
}
// Return a fresh Message object that can be used to
// construct the next packet in the sequence. Don't call
// unless ready() returns true.
Message& send(const Time& now, const Time::Duration& tls_timeout)
{
Message& msg = window_.ref_by_id(next);
msg.id_ = next++;
msg.reset_retransmit(now, tls_timeout);
return msg;
}
// Return true if send queue is ready to receive another packet
bool ready() const { return window_.in_window(next); }
// Remove a message from send queue that has been acknowledged
void ack(const id_t id) { window_.rm_by_id(id); }
private:
id_t next;
MessageWindow<Message, id_t> window_;
};
} // namespace openvpn
#endif // OPENVPN_RELIABLE_RELSEND_H