From f89cbb6981447b2ba7c6cbc3f314cc37fa2b881e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Bastian?= Date: Fri, 5 Jun 2020 17:31:02 +0200 Subject: [PATCH] Use new VpnPacket --- UdpVpn.cpp | 28 +++++++++++++++++++++---- UdpVpn.hpp | 5 +++++ UdpVpnClient.cpp | 41 ++++++++++++++----------------------- UdpVpnClient.hpp | 2 +- UdpVpnServer.cpp | 53 +++++++++++++++++++----------------------------- VpnPeer.cpp | 4 ++++ VpnPeer.hpp | 2 ++ 7 files changed, 72 insertions(+), 63 deletions(-) diff --git a/UdpVpn.cpp b/UdpVpn.cpp index a1e81a0..adb2344 100644 --- a/UdpVpn.cpp +++ b/UdpVpn.cpp @@ -11,8 +11,10 @@ #include "ip_header.hpp" +static const size_t VPN_MTU = 1500; // TODO determine this + 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); if(_socket < 0) @@ -69,11 +71,17 @@ void UdpVpn::run() { size_t UdpVpn::read_from_tun(char* buffer, size_t len) { // 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 nread; } @@ -104,3 +112,15 @@ size_t UdpVpn::read_from_udp(char* buffer, size_t len, 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; +} + diff --git a/UdpVpn.hpp b/UdpVpn.hpp index 6e59168..c0bdc47 100644 --- a/UdpVpn.hpp +++ b/UdpVpn.hpp @@ -6,6 +6,7 @@ #include "util.hpp" #include "TunDevice.hpp" #include "VpnPeer.hpp" +#include "VpnPacket.hpp" /** Handles UDP communication */ @@ -45,10 +46,14 @@ class UdpVpn { virtual void receive_from_udp() = 0; 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(VpnPacket& packet, sockaddr_in6& peer_addr); int _socket; bool _stopped; + size_t _vpn_mtu; + TunDevice _tun_dev; }; diff --git a/UdpVpnClient.cpp b/UdpVpnClient.cpp index 7c44e2d..fe73715 100644 --- a/UdpVpnClient.cpp +++ b/UdpVpnClient.cpp @@ -16,49 +16,38 @@ void UdpVpnClient::set_server(const struct sockaddr_in6& server_addr) { } void UdpVpnClient::receive_from_tun() { - char buffer[1500]; - size_t nread = read_from_tun(buffer, 1500); + VpnPacket packet(_vpn_mtu); + size_t nread = read_from_tun(packet); if(nread == 0) 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", - format_address(inner_header.source.s6_addr), - format_address(inner_header.dest.s6_addr), + format_address(packet.get_ipv6_header().source.s6_addr), + format_address(packet.get_ipv6_header().dest.s6_addr), nread); - write_to_server(buffer, nread); + write_to_server(packet); } void UdpVpnClient::receive_from_udp() { - char buffer[1500]; + VpnPacket packet(_vpn_mtu); sockaddr_in6 peer_addr; - size_t nread = read_from_udp(buffer, 1500, peer_addr); - - // 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"); + size_t nread = read_from_udp(packet, peer_addr); + if(nread == 0) return; - } // Reinject into tun - kdebugf("Receiving packet of size %d from peer\n", nread); - _tun_dev.write(buffer, nread); + kdebugf("Receiving packet of size %d from %s\n", + 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; - 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)); if(nsent < 0) throw NetError("Could not send UDP packet", errno, true); diff --git a/UdpVpnClient.hpp b/UdpVpnClient.hpp index 6227fec..86d455c 100644 --- a/UdpVpnClient.hpp +++ b/UdpVpnClient.hpp @@ -12,7 +12,7 @@ class UdpVpnClient: public UdpVpn { virtual void receive_from_tun(); 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; }; diff --git a/UdpVpnServer.cpp b/UdpVpnServer.cpp index d3946fe..ffc4488 100644 --- a/UdpVpnServer.cpp +++ b/UdpVpnServer.cpp @@ -42,63 +42,52 @@ std::shared_ptr UdpVpnServer::get_peer_for_ip( } void UdpVpnServer::receive_from_tun() { - char buffer[1500]; - size_t nread = read_from_tun(buffer, 1500); + VpnPacket packet(_vpn_mtu); + size_t nread = read_from_tun(packet); if(nread == 0) 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 - std::shared_ptr peer = get_peer_for_ip(inner_header.dest); + const in6_addr& peer_inner_addr = packet.get_ipv6_header().dest; + std::shared_ptr peer = get_peer_for_ip(peer_inner_addr); if(!peer) { debugf("Dropping packet for destination %s -- unknown peer.\n", - format_address(inner_header.dest.s6_addr)); + format_address(peer_inner_addr.s6_addr)); return; } kdebugf("Transmitting %s -> %s, size %d\n", - format_address(inner_header.source.s6_addr), - format_address(inner_header.dest.s6_addr), + format_address(packet.get_ipv6_header().source.s6_addr), + format_address(packet.get_ipv6_header().dest.s6_addr), nread); - peer->write(buffer, nread); + peer->write(packet); } void UdpVpnServer::receive_from_udp() { - char buffer[1500]; + VpnPacket packet(_vpn_mtu); sockaddr_in6 peer_addr; - size_t nread = read_from_udp(buffer, 1500, peer_addr); - - // 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"); + size_t nread = read_from_udp(packet, peer_addr); + if(nread == 0) return; - } // Recover VpnPeer -- or create if new - std::shared_ptr peer = get_peer_for_ip(inner_header.source); + const in6_addr& peer_inner_addr = packet.get_ipv6_header().source; + std::shared_ptr peer = get_peer_for_ip(peer_inner_addr); if(!peer) { - peer = std::make_shared(this, peer_addr, inner_header.source); - auto insert_result = _peers.insert({inner_header.source, peer}); + peer = std::make_shared(this, peer_addr, peer_inner_addr); + _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), htons(peer_addr.sin6_port), - format_address(inner_header.source.s6_addr), - insert_result.second); + format_address(peer_inner_addr.s6_addr)); } // VpnPeer* peer = (peer_iter->second); // TODO -- pass the packet to `peer` for a cleaner flow // Reinject into tun - kdebugf("Receiving packet of size %d from peer\n", nread); - _tun_dev.write(buffer, nread); + kdebugf("Receiving packet of size %d from %s\n", + nread, + format_address(packet.get_ipv6_header().source.s6_addr)); + _tun_dev.write(packet.get_payload(), packet.get_payload_size()); } diff --git a/VpnPeer.cpp b/VpnPeer.cpp index 0e93826..12218ff 100644 --- a/VpnPeer.cpp +++ b/VpnPeer.cpp @@ -21,3 +21,7 @@ size_t VpnPeer::write(const char* data, size_t len) { return (size_t) nsent; } + +size_t VpnPeer::write(const VpnPacket& packet) { + return write(packet.get_data(), packet.get_data_size()); +} diff --git a/VpnPeer.hpp b/VpnPeer.hpp index bc74834..aa72c75 100644 --- a/VpnPeer.hpp +++ b/VpnPeer.hpp @@ -4,6 +4,7 @@ #include #include "util.hpp" +#include "VpnPacket.hpp" class UdpVpn; @@ -25,6 +26,7 @@ class VpnPeer { const in6_addr& get_int_addr() const { return _int_addr; } size_t write(const char* data, size_t len); + size_t write(const VpnPacket& packet); private: UdpVpn* _vpn;