From 2bdac6139740e457125af65a0ad85693fb9054ee Mon Sep 17 00:00:00 2001 From: dr7ana Date: Sat, 7 Dec 2024 11:25:49 -0800 Subject: [PATCH] datagramIO --- llarp/address/ip_packet.cpp | 63 +++++++++++++++++-------------------- llarp/address/ip_packet.hpp | 12 ++----- llarp/dns/server.cpp | 2 +- llarp/dns/server.hpp | 2 +- llarp/handlers/session.cpp | 52 +++++++++++++----------------- llarp/handlers/tun.cpp | 2 ++ llarp/link/link_manager.cpp | 34 ++++++++++++++------ llarp/link/link_manager.hpp | 3 +- llarp/messages/path.hpp | 8 ++--- llarp/vpn/packet_router.cpp | 9 +++++- 10 files changed, 94 insertions(+), 93 deletions(-) diff --git a/llarp/address/ip_packet.cpp b/llarp/address/ip_packet.cpp index 3d1ebbccb6..e28fa45937 100644 --- a/llarp/address/ip_packet.cpp +++ b/llarp/address/ip_packet.cpp @@ -3,6 +3,7 @@ #include "utils.hpp" #include +#include #include #include @@ -27,18 +28,14 @@ namespace llarp IPPacket::IPPacket(ustring_view data) : IPPacket{data.data(), data.size()} {} - IPPacket::IPPacket(std::vector data) : IPPacket{data.data(), data.size()} {} + IPPacket::IPPacket(std::vector&& data) : IPPacket{data.data(), data.size()} {} IPPacket::IPPacket(const uint8_t* buf, size_t len) { - if (len < MIN_PACKET_SIZE) - { - _buf.resize(0); - } - else + if (len >= MIN_PACKET_SIZE) { _buf.resize(len); - std::copy_n(buf, len, _buf.data()); + std::memcpy(_buf.data(), buf, len); } _init_internals(); @@ -65,7 +62,14 @@ namespace llarp _header = reinterpret_cast(data()); _v6_header = reinterpret_cast(data()); - _is_v4 = _header->protocol == uint8_t{4}; + if (_buf.empty()) + return; + + // log::trace(logcat, "ippkt header: {}", buffer_printer{_buf}); + // log::trace(logcat, "ippkt protocol: {}", _header->protocol); + // log::trace(logcat, "ippkt version: {}", _header->version); + + _is_v4 = _header->version == oxenc::host_to_big(uint8_t{4}); _is_udp = _header->protocol == uint8_t{17}; uint16_t src_port = @@ -76,20 +80,24 @@ namespace llarp if (_is_v4) { - auto src = in_addr{_header->src}; - auto dest = in_addr{_header->dest}; + auto srcv4 = ipv4{oxenc::big_to_host(_header->src)}; + auto dstv4 = ipv4{oxenc::big_to_host(_header->dest)}; + + log::trace(logcat, "srcv4={}:{}, dstv4={}:{}", srcv4, src_port, dstv4, dest_port); - _src_addr.set_addr(&src); - _dst_addr.set_addr(&dest); + _src_addr = oxen::quic::Address{srcv4, src_port}; + _dst_addr = oxen::quic::Address{dstv4, dest_port}; } else { - _src_addr.set_addr(&_v6_header->srcaddr); - _dst_addr.set_addr(&_v6_header->dstaddr); - } + auto srcv6 = ipv6{&_v6_header->srcaddr}; + auto dstv6 = ipv6{&_v6_header->dstaddr}; + + log::trace(logcat, "srcv6={}:{}, dstv6={}:{}", srcv6, src_port, dstv6, dest_port); - _src_addr.set_port(src_port); - _dst_addr.set_port(dest_port); + _src_addr = oxen::quic::Address{srcv6, src_port}; + _dst_addr = oxen::quic::Address{dstv6, dest_port}; + } } std::optional> IPPacket::l4_data() const @@ -283,7 +291,7 @@ namespace llarp itr += 2; // copy ip header and first 8 bytes of datagram for icmp rject - std::copy_n(data(), ip_hdr_sz + ICMP_HEADER_SIZE, itr); + std::memcpy(itr, _buf.data(), ip_hdr_sz + ICMP_HEADER_SIZE); itr += ip_hdr_sz + ICMP_HEADER_SIZE; // calculate checksum of ip header @@ -302,21 +310,6 @@ namespace llarp return NetworkPacket{oxen::quic::Path{_src_addr, _dst_addr}, bview()}; } - bool IPPacket::load(ustring_view data) - { - return load(data.data(), data.size()); - } - - bool IPPacket::load(std::string_view data) - { - return load(reinterpret_cast(data.data()), data.size()); - } - - bool IPPacket::load(std::vector data) - { - return load(data.data(), data.size()); - } - bool IPPacket::load(const uint8_t* buf, size_t len) { if (len < MIN_PACKET_SIZE) @@ -324,7 +317,7 @@ namespace llarp _buf.clear(); _buf.resize(len); - std::copy_n(buf, len, _buf.data()); + std::memcpy(_buf.data(), buf, len); _init_internals(); @@ -376,7 +369,7 @@ namespace llarp std::string IPPacket::info_line() const { - return "IPPacket (src:{}, dest:{}, size:{})"_format(_src_addr, _dst_addr, size()); + return "IPPacket:[src={} | dest={} | size={}]"_format(_src_addr, _dst_addr, size()); } } // namespace llarp diff --git a/llarp/address/ip_packet.hpp b/llarp/address/ip_packet.hpp index 3c49ef8819..b2f879bbbd 100644 --- a/llarp/address/ip_packet.hpp +++ b/llarp/address/ip_packet.hpp @@ -32,7 +32,7 @@ namespace llarp struct IPPacket { private: - std::vector _buf; + std::vector _buf{}; ip_header* _header{}; ipv6_header* _v6_header{}; @@ -40,7 +40,7 @@ namespace llarp oxen::quic::Address _src_addr{}; oxen::quic::Address _dst_addr{}; - bool _is_v4{false}; + bool _is_v4{true}; bool _is_udp{false}; void _init_internals(); @@ -50,7 +50,7 @@ namespace llarp explicit IPPacket(size_t sz); explicit IPPacket(bstring_view data); explicit IPPacket(ustring_view data); - explicit IPPacket(std::vector data); + explicit IPPacket(std::vector&& data); explicit IPPacket(const uint8_t* buf, size_t len); static IPPacket from_netpkt(NetworkPacket pkt); @@ -109,12 +109,6 @@ namespace llarp bool empty() const { return _buf.empty(); } - bool load(ustring_view data); - - bool load(std::string_view data); - - bool load(std::vector data); - bool load(const uint8_t* buf, size_t len); // takes posession of the data diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index 5d31e199c1..a917e82f0e 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -501,7 +501,7 @@ namespace llarp::dns if (parent_ptr) { parent_ptr->call( - [self = shared_from_this(), parent_ptr = std::move(parent_ptr), buf = std::move(data)] { + [self = shared_from_this(), parent_ptr = std::move(parent_ptr), buf = std::move(data)]() mutable { log::trace( logcat, "forwarding dns response from libunbound to userland (resolverAddr: {}, " diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index 830a433f86..89be074512 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -136,7 +136,7 @@ namespace llarp::dns : QueryJob_Base{query}, src{std::move(source)}, resolver{to_}, asker{from_} {} - void send_reply(std::vector buf) override { src->send_to(asker, resolver, IPPacket{buf}); } + void send_reply(std::vector buf) override { src->send_to(asker, resolver, IPPacket{std::move(buf)}); } }; /// handler of dns query hooking diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index a082899b70..092bae9304 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -140,7 +140,7 @@ namespace llarp::handlers update_and_publish_localcc(get_current_client_intros(), _srv_records); } - static std::atomic testnet_trigger = false; + // static std::atomic testnet_trigger = false; void SessionEndpoint::start_tickers() { @@ -155,24 +155,25 @@ namespace llarp::handlers }, true); - if (not testnet_trigger) - { - testnet_trigger = true; - - _router.loop()->call_later(15s, [this]() { - try - { - RouterID cpk{oxenc::from_base32z("4bfu94cyd5t1976qubcwc3nirarri34o4pxq865xrd4krcs8tzxo")}; - log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); - _initiate_session( - NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); - } - catch (const std::exception& e) - { - log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); - } - }); - } + // if (not testnet_trigger) + // { + // testnet_trigger = true; + + // _router.loop()->call_later(10s, [this]() { + // try + // { + // RouterID cpk{oxenc::from_base32z("midg5wcgtjhkih6wchpc4k67jsce5ei8g7zfu99kdpdgsjfutidy")}; + // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); + // _initiate_session( + // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); + // }); + // } + // catch (const std::exception& e) + // { + // log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); + // } + // }); + // } } else log::info(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); @@ -590,17 +591,8 @@ namespace llarp::handlers log::trace(logcat, "inner payload: {}", buffer_printer{inner_payload}); - // add path-control wrapping for pivot to relay to aligned path - // auto& pivot = path->hops.back(); - auto onion_nonce = SymmNonce::make_random(); - // crypto::onion( - // reinterpret_cast(inner_payload.data()), - // inner_payload.size(), - // pivot.shared, - // onion_nonce, - // onion_nonce); - - auto pivot_payload = ONION::serialize_hop(remote_intro.pivot_txid.to_view(), onion_nonce, inner_payload); + auto pivot_payload = + ONION::serialize_hop(remote_intro.pivot_txid.to_view(), SymmNonce::make_random(), inner_payload); log::trace(logcat, "pivot payload: {}", buffer_printer{pivot_payload}); auto intermediate_payload = PATH::CONTROL::serialize("path_control", std::move(pivot_payload)); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 82513192ea..c7b7984b5e 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -965,6 +965,8 @@ namespace llarp::handlers auto pkt_is_ipv4 = pkt.is_ipv4(); + log::trace(logcat, "outbound packet is ipv{}", pkt_is_ipv4 ? "4" : "6"); + if (pkt_is_ipv4) { src = pkt.source_ipv4(); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 2bea82c8e7..02f700091d 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -329,7 +329,8 @@ namespace llarp [this](oxen::quic::connection_interface& ci, uint64_t ec) { return on_conn_closed(ci, ec); }, [this](oxen::quic::dgram_interface&, bstring dgram) { handle_path_data_message(std::move(dgram)); }, is_service_node() ? alpns::SERVICE_INBOUND : alpns::CLIENT_INBOUND, - is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND); + is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND, + oxen::quic::opt::enable_datagrams{oxen::quic::Splitting::ACTIVE}); // While only service nodes accept inbound connections, clients must have this key verify // callback set. It will reject any attempted inbound connection to a lokinet client prior @@ -1392,7 +1393,8 @@ namespace llarp log::info(logcat, "Received path control for local client: {}", buffer_printer{payload}); - for (size_t i = 0; i < path->hops.size() - 1; ++i) + // TESTNET: + for (size_t i = 0; i < path->hops.size() /* - 1 */; ++i) { auto& hop = path->hops[i]; nonce = crypto::onion( @@ -1418,16 +1420,15 @@ namespace llarp auto onion_nonce = nonce ^ hop->kx.xor_nonce; - // we only de-onion if we are NOT bridging a request over aligned paths + crypto::onion( + reinterpret_cast(payload.data()), + payload.size(), + hop->kx.shared_secret, + onion_nonce, + hop->kx.xor_nonce); + if (not inner_body.has_value()) { - crypto::onion( - reinterpret_cast(payload.data()), - payload.size(), - hop->kx.shared_secret, - onion_nonce, - hop->kx.xor_nonce); - // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. if (hop->terminal_hop) { @@ -1517,6 +1518,19 @@ namespace llarp return; } + if (!_is_service_node) + { + auto path = _router.path_context()->get_path(hop_id); + + if (not path) + { + log::warning(logcat, "Client received path data with unknown rxID: {}", hop_id); + return; + } + + log::info(logcat, "Received path data for local client: {}", buffer_printer{payload}); + } + auto hop = _router.path_context()->get_transit_hop(hop_id); if (not hop) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 157c55edac..2a554d224b 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -158,8 +158,6 @@ namespace llarp std::atomic is_stopping; - void handle_path_data_message(bstring dgram); - std::shared_ptr make_control( const std::shared_ptr& ci, const RouterID& rid); @@ -293,6 +291,7 @@ namespace llarp {"session_init"sv, &LinkManager::_handle_initiate_session}}; // Path relaying + void handle_path_data_message(bstring dgram); void handle_path_control(oxen::quic::message); void relay_path_request(oxen::quic::message m, std::string payload); diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index ee831c7725..e2aaea508e 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -268,7 +268,7 @@ namespace llarp { /** Fields for transmitting Path Data: - 'i' : RouterID of sender - - 'p' : request/command payload + - 'p' : messages payload NOTE: more fields may be added later as needed, hence the namespacing */ inline static std::string serialize(std::string payload, const RouterID& local) @@ -282,15 +282,15 @@ namespace llarp inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) { RouterID remote; - bstring body; + bstring payload; try { remote.from_string(btdc.require("i")); - body = btdc.require("p"); + payload = btdc.require("p"); auto sender = NetworkAddress::from_pubkey(remote, true); - return {std::move(sender), std::move(body)}; + return {std::move(sender), std::move(payload)}; } catch (const std::exception& e) { diff --git a/llarp/vpn/packet_router.cpp b/llarp/vpn/packet_router.cpp index 817c0a4967..4c99e6e08b 100644 --- a/llarp/vpn/packet_router.cpp +++ b/llarp/vpn/packet_router.cpp @@ -1,7 +1,11 @@ #include "packet_router.hpp" +#include + namespace llarp::vpn { + static auto logcat = log::Cat("ip_packet"); + struct UDPPacketHandler : public Layer4Handler { ip_pkt_hook _base_handler; @@ -16,6 +20,7 @@ namespace llarp::vpn void handle_ip_packet(IPPacket pkt) override { + log::debug(logcat, "inbound pkt: ", pkt.info_line()); auto dstport = pkt.dest_port(); if (not dstport) @@ -38,8 +43,9 @@ namespace llarp::vpn explicit GenericLayer4Handler(ip_pkt_hook baseHandler) : _base_handler{std::move(baseHandler)} {} - void handle_ip_packet(IPPacket) override + void handle_ip_packet(IPPacket pkt) override { + log::debug(logcat, "inbound pkt: {}", pkt.info_line()); // TOFIX: // _base_handler(IPPacket::from_udp(std::move(pkt))); } @@ -49,6 +55,7 @@ namespace llarp::vpn void PacketRouter::handle_ip_packet(IPPacket pkt) { + log::debug(logcat, "inbound pkt: {}", pkt.info_line()); auto dest_port = pkt.dest_port(); if (not dest_port)