Use new VpnPacket
This commit is contained in:
parent
50d28c0506
commit
f89cbb6981
7 changed files with 72 additions and 63 deletions
28
UdpVpn.cpp
28
UdpVpn.cpp
|
@ -11,8 +11,10 @@
|
||||||
|
|
||||||
#include "ip_header.hpp"
|
#include "ip_header.hpp"
|
||||||
|
|
||||||
|
static const size_t VPN_MTU = 1500; // TODO determine this
|
||||||
|
|
||||||
UdpVpn::UdpVpn()
|
UdpVpn::UdpVpn()
|
||||||
: _stopped(false), _tun_dev("cvpn%d")
|
: _stopped(false), _vpn_mtu(VPN_MTU), _tun_dev("cvpn%d")
|
||||||
{
|
{
|
||||||
_socket = socket(AF_INET6, SOCK_DGRAM, 0);
|
_socket = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
if(_socket < 0)
|
if(_socket < 0)
|
||||||
|
@ -69,11 +71,17 @@ void UdpVpn::run() {
|
||||||
|
|
||||||
size_t UdpVpn::read_from_tun(char* buffer, size_t len) {
|
size_t UdpVpn::read_from_tun(char* buffer, size_t len) {
|
||||||
// We know that there is data available -- use `read()`
|
// We know that there is data available -- use `read()`
|
||||||
size_t nread = _tun_dev.read(buffer, len);
|
return _tun_dev.read(buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
if(nread == 0)
|
size_t UdpVpn::read_from_tun(VpnPacket& packet) {
|
||||||
|
size_t nread =
|
||||||
|
read_from_tun(packet.get_payload(), packet.get_payload_space());
|
||||||
|
packet.set_payload_size(nread);
|
||||||
|
if(!packet.parse_as_ipv6()) {
|
||||||
|
debugf("Ignoring packet with invalid header\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,3 +112,15 @@ size_t UdpVpn::read_from_udp(char* buffer, size_t len,
|
||||||
|
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t UdpVpn::read_from_udp(VpnPacket& packet, sockaddr_in6& peer_addr) {
|
||||||
|
size_t nread =
|
||||||
|
read_from_udp(packet.get_data(), packet.get_data_space(), peer_addr);
|
||||||
|
packet.set_data_size(nread);
|
||||||
|
if(!packet.parse_as_ipv6()) {
|
||||||
|
debugf("Ignoring packet with invalid header\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "TunDevice.hpp"
|
#include "TunDevice.hpp"
|
||||||
#include "VpnPeer.hpp"
|
#include "VpnPeer.hpp"
|
||||||
|
#include "VpnPacket.hpp"
|
||||||
|
|
||||||
/** Handles UDP communication */
|
/** Handles UDP communication */
|
||||||
|
|
||||||
|
@ -45,10 +46,14 @@ class UdpVpn {
|
||||||
virtual void receive_from_udp() = 0;
|
virtual void receive_from_udp() = 0;
|
||||||
|
|
||||||
size_t read_from_tun(char* buffer, size_t len);
|
size_t read_from_tun(char* buffer, size_t len);
|
||||||
|
size_t read_from_tun(VpnPacket& packet);
|
||||||
size_t read_from_udp(char* buffer, size_t len, sockaddr_in6& peer_addr);
|
size_t read_from_udp(char* buffer, size_t len, sockaddr_in6& peer_addr);
|
||||||
|
size_t read_from_udp(VpnPacket& packet, sockaddr_in6& peer_addr);
|
||||||
|
|
||||||
int _socket;
|
int _socket;
|
||||||
bool _stopped;
|
bool _stopped;
|
||||||
|
|
||||||
|
size_t _vpn_mtu;
|
||||||
|
|
||||||
TunDevice _tun_dev;
|
TunDevice _tun_dev;
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,49 +16,38 @@ void UdpVpnClient::set_server(const struct sockaddr_in6& server_addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UdpVpnClient::receive_from_tun() {
|
void UdpVpnClient::receive_from_tun() {
|
||||||
char buffer[1500];
|
VpnPacket packet(_vpn_mtu);
|
||||||
size_t nread = read_from_tun(buffer, 1500);
|
size_t nread = read_from_tun(packet);
|
||||||
if(nread == 0)
|
if(nread == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Parse inner packet header -- assume IPv6 for now [FIXME]
|
|
||||||
IPv6Header inner_header;
|
|
||||||
if(!parse_ipv6_header(buffer, nread, inner_header)) {
|
|
||||||
// Not a valid header -- ignore the packet
|
|
||||||
debugf("Ignoring outgoing packet with invalid header\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
kdebugf("Transmitting %s -> %s, size %d\n",
|
kdebugf("Transmitting %s -> %s, size %d\n",
|
||||||
format_address(inner_header.source.s6_addr),
|
format_address(packet.get_ipv6_header().source.s6_addr),
|
||||||
format_address(inner_header.dest.s6_addr),
|
format_address(packet.get_ipv6_header().dest.s6_addr),
|
||||||
nread);
|
nread);
|
||||||
|
|
||||||
write_to_server(buffer, nread);
|
write_to_server(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UdpVpnClient::receive_from_udp() {
|
void UdpVpnClient::receive_from_udp() {
|
||||||
char buffer[1500];
|
VpnPacket packet(_vpn_mtu);
|
||||||
sockaddr_in6 peer_addr;
|
sockaddr_in6 peer_addr;
|
||||||
size_t nread = read_from_udp(buffer, 1500, peer_addr);
|
size_t nread = read_from_udp(packet, peer_addr);
|
||||||
|
if(nread == 0)
|
||||||
// Parse inner packet header -- assume IPv6 for now [FIXME]
|
|
||||||
IPv6Header inner_header;
|
|
||||||
if(!parse_ipv6_header(buffer, nread, inner_header)) {
|
|
||||||
// Not a valid header -- ignore the packet
|
|
||||||
debugf("Ignoring packet with invalid header\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Reinject into tun
|
// Reinject into tun
|
||||||
kdebugf("Receiving packet of size %d from peer\n", nread);
|
kdebugf("Receiving packet of size %d from %s\n",
|
||||||
_tun_dev.write(buffer, nread);
|
nread,
|
||||||
|
format_address(packet.get_ipv6_header().source.s6_addr));
|
||||||
|
_tun_dev.write(packet.get_payload(), packet.get_payload_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t UdpVpnClient::write_to_server(const char* data, size_t len) {
|
size_t UdpVpnClient::write_to_server(const VpnPacket& packet) {
|
||||||
ssize_t nsent;
|
ssize_t nsent;
|
||||||
|
|
||||||
nsent = sendto(_socket, data, len, MSG_CONFIRM,
|
nsent = sendto(_socket, packet.get_data(), packet.get_data_size(),
|
||||||
|
MSG_CONFIRM,
|
||||||
(const struct sockaddr*) &_server_addr, sizeof(_server_addr));
|
(const struct sockaddr*) &_server_addr, sizeof(_server_addr));
|
||||||
if(nsent < 0)
|
if(nsent < 0)
|
||||||
throw NetError("Could not send UDP packet", errno, true);
|
throw NetError("Could not send UDP packet", errno, true);
|
||||||
|
|
|
@ -12,7 +12,7 @@ class UdpVpnClient: public UdpVpn {
|
||||||
virtual void receive_from_tun();
|
virtual void receive_from_tun();
|
||||||
virtual void receive_from_udp();
|
virtual void receive_from_udp();
|
||||||
|
|
||||||
size_t write_to_server(const char* data, size_t len);
|
size_t write_to_server(const VpnPacket& packet);
|
||||||
|
|
||||||
struct sockaddr_in6 _server_addr;
|
struct sockaddr_in6 _server_addr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,63 +42,52 @@ std::shared_ptr<VpnPeer> UdpVpnServer::get_peer_for_ip(
|
||||||
}
|
}
|
||||||
|
|
||||||
void UdpVpnServer::receive_from_tun() {
|
void UdpVpnServer::receive_from_tun() {
|
||||||
char buffer[1500];
|
VpnPacket packet(_vpn_mtu);
|
||||||
size_t nread = read_from_tun(buffer, 1500);
|
size_t nread = read_from_tun(packet);
|
||||||
if(nread == 0)
|
if(nread == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Parse inner packet header -- assume IPv6 for now [FIXME]
|
|
||||||
IPv6Header inner_header;
|
|
||||||
if(!parse_ipv6_header(buffer, nread, inner_header)) {
|
|
||||||
// Not a valid header -- ignore the packet
|
|
||||||
debugf("Ignoring outgoing packet with invalid header\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recover VpnPeer -- or drop if new
|
// Recover VpnPeer -- or drop if new
|
||||||
std::shared_ptr<VpnPeer> peer = get_peer_for_ip(inner_header.dest);
|
const in6_addr& peer_inner_addr = packet.get_ipv6_header().dest;
|
||||||
|
std::shared_ptr<VpnPeer> peer = get_peer_for_ip(peer_inner_addr);
|
||||||
if(!peer) {
|
if(!peer) {
|
||||||
debugf("Dropping packet for destination %s -- unknown peer.\n",
|
debugf("Dropping packet for destination %s -- unknown peer.\n",
|
||||||
format_address(inner_header.dest.s6_addr));
|
format_address(peer_inner_addr.s6_addr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
kdebugf("Transmitting %s -> %s, size %d\n",
|
kdebugf("Transmitting %s -> %s, size %d\n",
|
||||||
format_address(inner_header.source.s6_addr),
|
format_address(packet.get_ipv6_header().source.s6_addr),
|
||||||
format_address(inner_header.dest.s6_addr),
|
format_address(packet.get_ipv6_header().dest.s6_addr),
|
||||||
nread);
|
nread);
|
||||||
peer->write(buffer, nread);
|
peer->write(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UdpVpnServer::receive_from_udp() {
|
void UdpVpnServer::receive_from_udp() {
|
||||||
char buffer[1500];
|
VpnPacket packet(_vpn_mtu);
|
||||||
sockaddr_in6 peer_addr;
|
sockaddr_in6 peer_addr;
|
||||||
size_t nread = read_from_udp(buffer, 1500, peer_addr);
|
size_t nread = read_from_udp(packet, peer_addr);
|
||||||
|
if(nread == 0)
|
||||||
// Parse inner packet header -- assume IPv6 for now [FIXME]
|
|
||||||
IPv6Header inner_header;
|
|
||||||
if(!parse_ipv6_header(buffer, nread, inner_header)) {
|
|
||||||
// Not a valid header -- ignore the packet
|
|
||||||
debugf("Ignoring packet with invalid header\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Recover VpnPeer -- or create if new
|
// Recover VpnPeer -- or create if new
|
||||||
std::shared_ptr<VpnPeer> peer = get_peer_for_ip(inner_header.source);
|
const in6_addr& peer_inner_addr = packet.get_ipv6_header().source;
|
||||||
|
std::shared_ptr<VpnPeer> peer = get_peer_for_ip(peer_inner_addr);
|
||||||
if(!peer) {
|
if(!peer) {
|
||||||
peer = std::make_shared<VpnPeer>(this, peer_addr, inner_header.source);
|
peer = std::make_shared<VpnPeer>(this, peer_addr, peer_inner_addr);
|
||||||
auto insert_result = _peers.insert({inner_header.source, peer});
|
_peers.insert({peer_inner_addr, peer});
|
||||||
|
|
||||||
debugf("Got new peer %s:%d -- %s [really inserted=%d]\n",
|
debugf("Got new peer %s:%d -- %s\n",
|
||||||
format_address(peer_addr.sin6_addr.s6_addr),
|
format_address(peer_addr.sin6_addr.s6_addr),
|
||||||
htons(peer_addr.sin6_port),
|
htons(peer_addr.sin6_port),
|
||||||
format_address(inner_header.source.s6_addr),
|
format_address(peer_inner_addr.s6_addr));
|
||||||
insert_result.second);
|
|
||||||
}
|
}
|
||||||
// VpnPeer* peer = (peer_iter->second);
|
// VpnPeer* peer = (peer_iter->second);
|
||||||
// TODO -- pass the packet to `peer` for a cleaner flow
|
// TODO -- pass the packet to `peer` for a cleaner flow
|
||||||
|
|
||||||
// Reinject into tun
|
// Reinject into tun
|
||||||
kdebugf("Receiving packet of size %d from peer\n", nread);
|
kdebugf("Receiving packet of size %d from %s\n",
|
||||||
_tun_dev.write(buffer, nread);
|
nread,
|
||||||
|
format_address(packet.get_ipv6_header().source.s6_addr));
|
||||||
|
_tun_dev.write(packet.get_payload(), packet.get_payload_size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,3 +21,7 @@ size_t VpnPeer::write(const char* data, size_t len) {
|
||||||
|
|
||||||
return (size_t) nsent;
|
return (size_t) nsent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t VpnPeer::write(const VpnPacket& packet) {
|
||||||
|
return write(packet.get_data(), packet.get_data_size());
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
#include "VpnPacket.hpp"
|
||||||
|
|
||||||
class UdpVpn;
|
class UdpVpn;
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ class VpnPeer {
|
||||||
const in6_addr& get_int_addr() const { return _int_addr; }
|
const in6_addr& get_int_addr() const { return _int_addr; }
|
||||||
|
|
||||||
size_t write(const char* data, size_t len);
|
size_t write(const char* data, size_t len);
|
||||||
|
size_t write(const VpnPacket& packet);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UdpVpn* _vpn;
|
UdpVpn* _vpn;
|
||||||
|
|
Loading…
Reference in a new issue