From b3d36651004e8124d9410e249215997a108473ec Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 22 Jun 2021 21:44:01 +0200 Subject: [PATCH] Handle raw packets from tiny peers. Tiny peers don't support UTCP channels, but send raw packets directly over the meta connection. --- src/connection.h | 1 + src/meshlink.c | 4 +--- src/meshlink_internal.h | 1 + src/meta.c | 14 ++++++++++---- src/net_packet.c | 5 +++++ src/protocol.c | 2 ++ src/protocol.h | 2 ++ src/protocol_misc.c | 13 +++++++++++++ src/route.c | 4 +++- 9 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/connection.h b/src/connection.h index 68d9e971..5e3a7ac7 100644 --- a/src/connection.h +++ b/src/connection.h @@ -41,6 +41,7 @@ typedef struct connection_status_t { uint16_t invitation: 1; /* 1 if this is an invitation */ uint16_t invitation_used: 1; /* 1 if the invitation has been consumed */ uint16_t initiator: 1; /* 1 if we initiated this connection */ + uint16_t raw_packet: 1; /* 1 if we are expecting a raw packet next */ } connection_status_t; #include "ecdsa.h" diff --git a/src/meshlink.c b/src/meshlink.c index 4cc285de..f153f757 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -4034,7 +4034,7 @@ void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t channel->receive_cb = cb; } -static void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) { +void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) { (void)mesh; node_t *n = (node_t *)source; @@ -4188,7 +4188,6 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac } mesh->channel_accept_cb = cb; - mesh->receive_cb = channel_receive; for splay_each(node_t, n, mesh->nodes) { if(!n->utcp && n != mesh->self) { @@ -4283,7 +4282,6 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t)); utcp_set_retransmit_cb(n->utcp, channel_retransmit); - mesh->receive_cb = channel_receive; if(!n->utcp) { meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL; diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index 26186015..469a05b1 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -250,6 +250,7 @@ extern meshlink_log_cb_t global_log_cb; void handle_duplicate_node(meshlink_handle_t *mesh, struct node_t *n); void handle_network_change(meshlink_handle_t *mesh, bool online); void call_error_cb(meshlink_handle_t *mesh, meshlink_errno_t meshlink_errno); +void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *node, const void *data, size_t len); /// Per-instance PRNG static inline int prng(meshlink_handle_t *mesh, uint64_t max) { diff --git a/src/meta.c b/src/meta.c index 13024677..a023d2a5 100644 --- a/src/meta.c +++ b/src/meta.c @@ -47,7 +47,7 @@ bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t leng bool send_meta(meshlink_handle_t *mesh, connection_t *c, const char *buffer, int length) { assert(c); assert(buffer); - assert(length); + assert(length >= 0); logger(mesh, MESHLINK_DEBUG, "Sending %d bytes of metadata to %s", length, c->name); @@ -107,10 +107,16 @@ bool receive_meta_sptps(void *handle, uint8_t type, const void *data, uint16_t l return true; } - /* Are we receiving a TCPpacket? */ + /* Are we receiving a raw packet? */ + + if(c->status.raw_packet) { + c->status.raw_packet = false; - if(c->tcplen) { - abort(); // TODO: get rid of tcplen altogether + if(mesh->receive_cb) { + mesh->receive_cb(mesh, (meshlink_node_t *)c->node, data, length); + } + + return true; } /* Change newline to null byte, just like non-SPTPS requests */ diff --git a/src/net_packet.c b/src/net_packet.c index 02a617d1..67fadfc5 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -279,6 +279,11 @@ static void send_sptps_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t * } if(!n->status.validkey) { + if(n->connection && (n->connection->flags & PROTOCOL_TINY) & n->connection->status.active) { + send_raw_packet(mesh, n->connection, origpkt); + return; + } + logger(mesh, MESHLINK_INFO, "No valid key known yet for %s", n->name); if(!n->status.waitingforkey) { diff --git a/src/protocol.c b/src/protocol.c index 9d1dff97..9975402c 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -44,6 +44,7 @@ static bool (*request_handlers[NUM_REQUESTS])(meshlink_handle_t *, connection_t [KEY_CHANGED] = key_changed_h, [REQ_KEY] = req_key_h, [ANS_KEY] = ans_key_h, + [PACKET] = raw_packet_h, }; /* Request names */ @@ -61,6 +62,7 @@ static const char *request_name[NUM_REQUESTS] = { [KEY_CHANGED] = "KEY_CHANGED", [REQ_KEY] = "REQ_KEY", [ANS_KEY] = "ANS_KEY", + [PACKET] = "PACKET", }; bool check_id(const char *id) { diff --git a/src/protocol.h b/src/protocol.h index 05c2203b..94f760f1 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -100,6 +100,7 @@ bool send_add_edge(struct meshlink_handle *mesh, struct connection_t *, const st bool send_del_edge(struct meshlink_handle *mesh, struct connection_t *, const struct edge_t *, int contradictions); bool send_req_key(struct meshlink_handle *mesh, struct node_t *); bool send_canonical_address(struct meshlink_handle *mesh, struct node_t *); +bool send_raw_packet(struct meshlink_handle *mesh, struct connection_t *, const vpn_packet_t *); /* Request handlers */ @@ -116,5 +117,6 @@ bool key_changed_h(struct meshlink_handle *mesh, struct connection_t *, const ch bool req_key_h(struct meshlink_handle *mesh, struct connection_t *, const char *); bool ans_key_h(struct meshlink_handle *mesh, struct connection_t *, const char *); bool tcppacket_h(struct meshlink_handle *mesh, struct connection_t *, const char *); +bool raw_packet_h(struct meshlink_handle *mesh, struct connection_t *, const char *); #endif diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 7410ad13..65895437 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -145,3 +145,16 @@ bool tcppacket_h(meshlink_handle_t *mesh, connection_t *c, const char *request) // This should never happen with MeshLink. return false; } + +bool send_raw_packet(meshlink_handle_t *mesh, connection_t *c, const vpn_packet_t *packet) { + size_t hdrsize = sizeof(meshlink_packethdr_t); + assert(packet->len >= hdrsize); + return send_request(mesh, c, NULL, "%d", PACKET) && send_meta(mesh, c, (const char *)packet->data + hdrsize, packet->len - hdrsize); +} + +bool raw_packet_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + (void)mesh; + (void)request; + c->status.raw_packet = true; + return true; +} diff --git a/src/route.c b/src/route.c index ee36a9bf..ea3a5434 100644 --- a/src/route.c +++ b/src/route.c @@ -69,7 +69,9 @@ void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) { logger(mesh, MESHLINK_DEBUG, "I received a packet for me with payload: %s\n", hex); - if(mesh->receive_cb) { + if(source->utcp) { + channel_receive(mesh, (meshlink_node_t *)source, payload, len); + } else if(mesh->receive_cb) { mesh->receive_cb(mesh, (meshlink_node_t *)source, payload, len); } -- 2.39.2