#include "utils.h"
#include "xalloc.h"
-void init_connections(void) {
+void init_connections(meshlink_handle_t *mesh) {
mesh->connections = list_alloc((list_action_t) free_connection);
mesh->everyone = new_connection();
mesh->everyone->name = xstrdup("mesh->everyone");
mesh->everyone->hostname = xstrdup("BROADCAST");
}
-void exit_connections(void) {
+void exit_connections(meshlink_handle_t *mesh) {
list_delete_list(mesh->connections);
free_connection(mesh->everyone);
}
buffer_clear(&c->inbuf);
buffer_clear(&c->outbuf);
- io_del(&mesh->loop, &c->io);
+ if(c->io.cb)
+ abort();
if(c->socket > 0)
closesocket(c->socket);
free(c);
}
-void connection_add(connection_t *c) {
+void connection_add(meshlink_handle_t *mesh, connection_t *c) {
+ c->mesh = mesh;
list_insert_tail(mesh->connections, c);
}
-void connection_del(connection_t *c) {
+void connection_del(meshlink_handle_t *mesh, connection_t *c) {
+ io_del(&mesh->loop, &c->io);
list_delete(mesh->connections, c);
}
struct timeval start; /* time this connection was started, used for above estimation */
struct outgoing_t *outgoing; /* used to keep track of outgoing connections */
+ struct meshlink_handle *mesh; /* the mesh this connection belongs to */
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
splay_tree_t *config_tree; /* Pointer to configuration tree belonging to him */
} connection_t;
-extern void init_connections(void);
-extern void exit_connections(void);
+extern void init_connections(struct meshlink_handle *mesh);
+extern void exit_connections(struct meshlink_handle *mesh);
extern connection_t *new_connection(void) __attribute__ ((__malloc__));
extern void free_connection(connection_t *);
-extern void connection_add(connection_t *);
-extern void connection_del(connection_t *);
+extern void connection_add(struct meshlink_handle *mesh, connection_t *);
+extern void connection_del(struct meshlink_handle *mesh, connection_t *);
#endif /* __TINC_CONNECTION_H__ */
return strcmp(a->to->name, b->to->name);
}
-void init_edges(void) {
+void init_edges(meshlink_handle_t *mesh) {
mesh->edges = splay_alloc_tree((splay_compare_t) edge_weight_compare, NULL);
}
splay_delete_tree(edge_tree);
}
-void exit_edges(void) {
+void exit_edges(meshlink_handle_t *mesh) {
splay_delete_tree(mesh->edges);
}
free(e);
}
-void edge_add(edge_t *e) {
+void edge_add(meshlink_handle_t *mesh, edge_t *e) {
splay_insert(mesh->edges, e);
splay_insert(e->from->edge_tree, e);
e->reverse->reverse = e;
}
-void edge_del(edge_t *e) {
+void edge_del(meshlink_handle_t *mesh, edge_t *e) {
if(e->reverse)
e->reverse->reverse = NULL;
struct edge_t *reverse; /* edge in the opposite direction, if available */
} edge_t;
-extern void init_edges(void);
-extern void exit_edges(void);
+extern void init_edges(struct meshlink_handle *mesh);
+extern void exit_edges(struct meshlink_handle *mesh);
extern edge_t *new_edge(void) __attribute__ ((__malloc__));
extern void free_edge(edge_t *);
extern struct splay_tree_t *new_edge_tree(void) __attribute__ ((__malloc__));
extern void free_edge_tree(struct splay_tree_t *);
-extern void edge_add(edge_t *);
-extern void edge_del(edge_t *);
+extern void edge_add(struct meshlink_handle *mesh, edge_t *);
+extern void edge_del(struct meshlink_handle *mesh, edge_t *);
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
#endif /* __TINC_EDGE_H__ */
Please note that sorting on weight is already done by add_edge().
*/
-static void mst_kruskal(void) {
+static void mst_kruskal(meshlink_handle_t *mesh) {
/* Clear MST status on connections */
for list_each(connection_t, c, mesh->connections)
Running time: O(E)
*/
-static void sssp_bfs(void) {
+static void sssp_bfs(meshlink_handle_t *mesh) {
list_t *todo_list = list_alloc(NULL);
/* Clear visited status on nodes */
e->to->distance = n->distance + 1;
if(!e->to->status.reachable || (e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN))
- update_node_udp(e->to, &e->address);
+ update_node_udp(mesh, e->to, &e->address);
list_insert_tail(todo_list, e->to);
}
list_free(todo_list);
}
-static void check_reachability(void) {
+static void check_reachability(meshlink_handle_t *mesh) {
/* Check reachability status. */
for splay_each(node_t, n, mesh->nodes) {
//TODO: callback to application to inform of this node going up/down
if(!n->status.reachable) {
- update_node_udp(n, NULL);
+ update_node_udp(mesh, n, NULL);
memset(&n->status, 0, sizeof n->status);
n->options = 0;
} else if(n->connection) {
if(n->connection->outgoing)
- send_req_key(n);
+ send_req_key(mesh, n);
}
}
}
}
-void graph(void) {
- sssp_bfs();
- check_reachability();
- mst_kruskal();
+void graph(meshlink_handle_t *mesh) {
+ sssp_bfs(mesh);
+ check_reachability(mesh);
+ mst_kruskal(mesh);
}
#ifndef __TINC_GRAPH_H__
#define __TINC_GRAPH_H__
-extern void graph(void);
+extern void graph(struct meshlink_handle *mesh);
#endif /* __TINC_GRAPH_H__ */
#include "meshlink_internal.h"
#include "sptps.h"
+// TODO: refactor logging code to use a meshlink_handle_t *.
void logger(int level, int priority, const char *format, ...) {
- if(level > mesh->debug_level)
- return;
+ //if(level > mesh->debug_level)
+ // return;
va_list ap;
char message[1024] = "";
#include "route.h"
#include "xalloc.h"
-meshlink_handle_t *mesh;
-
static const char *errstr[] = {
[MESHLINK_OK] = "No error",
[MESHLINK_ENOMEM] = "Out of memory",
return errstr[errno];
}
-// TODO: hack, remove once all global variables are gone.
-static void set_mesh(meshlink_handle_t *localmesh) {
- mesh = localmesh;
-}
-
static bool ecdsa_keygen(meshlink_handle_t *mesh) {
ecdsa_t *key;
FILE *f;
mesh->name = xstrdup(name);
event_loop_init(&mesh->loop);
mesh->loop.data = mesh;
- set_mesh(mesh);
// TODO: should be set by a function.
mesh->debug_level = 5;
mesh->self->in_packets++;
mesh->self->in_bytes += packet.len;
- route(mesh->self, &packet);
+ route(mesh, mesh->self, &packet);
return false;
}
meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) {
- return (meshlink_node_t *)lookup_node(name);
+ return (meshlink_node_t *)lookup_node(mesh, name);
return NULL;
}
void *priv;
};
-// This is a *temporary* global variable which will keep the compiler happy
-// while refactoring the code to get rid of global variables.
-// TODO: remove this when no other global variables remain.
-
-extern meshlink_handle_t *mesh;
-
/// Header for data packets routed between nodes
typedef struct meshlink_packethdr {
uint8_t destination[16];
bool send_meta_sptps(void *handle, uint8_t type, const char *buffer, size_t length) {
connection_t *c = handle;
+ meshlink_handle_t *mesh = c->mesh;
if(!c) {
logger(DEBUG_ALWAYS, LOG_ERR, "send_meta_sptps() called with NULL pointer!");
return true;
}
-bool send_meta(connection_t *c, const char *buffer, int length) {
+bool send_meta(meshlink_handle_t *mesh, connection_t *c, const char *buffer, int length) {
if(!c) {
logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
abort();
return sptps_send_record(&c->sptps, 0, buffer, length);
}
-void broadcast_meta(connection_t *from, const char *buffer, int length) {
+void broadcast_meta(meshlink_handle_t *mesh, connection_t *from, const char *buffer, int length) {
for list_each(connection_t, c, mesh->connections)
if(c != from && c->status.active)
- send_meta(c, buffer, length);
+ send_meta(mesh, c, buffer, length);
}
bool receive_meta_sptps(void *handle, uint8_t type, const char *data, uint16_t length) {
connection_t *c = handle;
+ meshlink_handle_t *mesh = c->mesh;
if(!c) {
logger(DEBUG_ALWAYS, LOG_ERR, "receive_meta_sptps() called with NULL pointer!");
if(type == SPTPS_HANDSHAKE) {
if(c->allow_request == ACK)
- return send_ack(c);
+ return send_ack(mesh, c);
else
return true;
}
/* Otherwise we are waiting for a request */
- return receive_request(c, data);
+ return receive_request(mesh, c, data);
}
-bool receive_meta(connection_t *c) {
+bool receive_meta(meshlink_handle_t *mesh, connection_t *c) {
int inlen;
char inbuf[MAXBUFSIZE];
char *bufp = inbuf, *endp;
while(c->inbuf.len) {
char *request = buffer_readline(&c->inbuf);
if(request) {
- bool result = receive_request(c, request);
+ bool result = receive_request(mesh, c, request);
if(!result)
return false;
continue;
#include "connection.h"
-extern bool send_meta(struct connection_t *, const char *, int);
+extern bool send_meta(struct meshlink_handle *mesh, struct connection_t *, const char *, int);
extern bool send_meta_sptps(void *, uint8_t, const char *, size_t);
extern bool receive_meta_sptps(void *, uint8_t, const char *, uint16_t);
-extern void broadcast_meta(struct connection_t *, const char *, int);
-extern bool receive_meta(struct connection_t *);
+extern void broadcast_meta(struct meshlink_handle *mesh, struct connection_t *, const char *, int);
+extern bool receive_meta(struct meshlink_handle *mesh, struct connection_t *);
#endif /* __TINC_META_H__ */
if(c->edge) {
if(report)
- send_del_edge(mesh->everyone, c->edge);
+ send_del_edge(mesh, mesh->everyone, c->edge);
- edge_del(c->edge);
+ edge_del(mesh, c->edge);
c->edge = NULL;
/* Run MST and SSSP algorithms */
- graph();
+ graph(mesh);
/* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
edge_t *e;
e = lookup_edge(c->node, mesh->self);
if(e) {
- send_del_edge(mesh->everyone, e);
- edge_del(e);
+ send_del_edge(mesh, mesh->everyone, e);
+ edge_del(mesh, e);
}
}
}
outgoing_t *outgoing = c->outgoing;
- connection_del(c);
+ connection_del(mesh, c);
/* Check if this was our outgoing connection */
if(c->status.pinged) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)mesh->loop.now.tv_sec - c->last_ping_time);
} else if(c->last_ping_time + mesh->pinginterval <= mesh->loop.now.tv_sec) {
- send_ping(c);
+ send_ping(mesh, c);
continue;
} else {
continue;
}
void handle_meta_connection_data(meshlink_handle_t *mesh, connection_t *c) {
- if (!receive_meta(c)) {
+ if (!receive_meta(mesh, c)) {
terminate_connection(mesh, c, c->status.active);
return;
}
n->in_packets++;
n->in_bytes += packet->len;
- route(n, packet);
+ route(mesh, n, packet);
}
static bool try_mac(meshlink_handle_t *mesh, node_t *n, const vpn_packet_t *inpkt) {
if(!n->sptps.state) {
if(!n->status.waitingforkey) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but we haven't exchanged keys yet", n->name, n->hostname);
- send_req_key(n);
+ send_req_key(mesh, n);
} else {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname);
}
if(!n->status.validkey) {
logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname);
if(!n->status.waitingforkey)
- send_req_key(n);
+ send_req_key(mesh, n);
else if(n->last_req_key + 10 < mesh->loop.now.tv_sec) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "No key from %s after 10 seconds, restarting SPTPS", n->name);
sptps_stop(&n->sptps);
n->status.waitingforkey = false;
- send_req_key(n);
+ send_req_key(mesh, n);
}
return;
}
bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
node_t *to = handle;
+ meshlink_handle_t *mesh = to->mesh;
/* Send it via TCP if it is a handshake packet, TCPOnly is in use, or this packet is larger than the MTU. */
to ensure we get to learn the reflexive UDP address. */
if(!to->status.validkey) {
to->incompression = mesh->self->incompression;
- return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, to->incompression);
+ return send_request(mesh, to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, to->incompression);
} else {
- return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf);
+ return send_request(mesh, to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf);
}
}
bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t len) {
node_t *from = handle;
+ meshlink_handle_t *mesh = from->mesh;
if(type == SPTPS_HANDSHAKE) {
if(!from->status.validkey) {
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
- n = lookup_node_udp(&from);
+ n = lookup_node_udp(mesh, &from);
if(!n) {
n = try_harder(mesh, &from, &pkt);
if(n)
- update_node_udp(n, &from);
+ update_node_udp(mesh, n, &from);
else if(mesh->debug_level >= DEBUG_PROTOCOL) {
hostname = sockaddr2hostname(&from);
logger(DEBUG_PROTOCOL, LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
if(!check_id(ent->d_name))
continue;
- node_t *n = lookup_node(ent->d_name);
+ node_t *n = lookup_node(mesh, ent->d_name);
if(n)
continue;
n = new_node();
n->name = xstrdup(ent->d_name);
- node_add(n);
+ node_add(mesh, n);
}
closedir(dir);
mesh->self->via = mesh->self;
mesh->self->status.reachable = true;
mesh->self->last_state_change = mesh->loop.now.tv_sec;
- node_add(mesh->self);
+ node_add(mesh, mesh->self);
- graph();
+ graph(mesh);
if(autoconnect)
load_all_nodes(mesh);
initialize network
*/
bool setup_network(meshlink_handle_t *mesh) {
- init_connections();
- init_nodes();
- init_edges();
- init_requests();
+ init_connections(mesh);
+ init_nodes(mesh);
+ init_edges(mesh);
+ init_requests(mesh);
mesh->pinginterval = 60;
mesh->pingtimeout = 5;
close(mesh->listen_socket[i].udp.fd);
}
- exit_requests();
- exit_edges();
- exit_nodes();
- exit_connections();
+ exit_requests(mesh);
+ exit_edges(mesh);
+ exit_nodes(mesh);
+ exit_connections(mesh);
if(mesh->myport) free(mesh->myport);
c->last_ping_time = mesh->loop.now.tv_sec;
c->status.connecting = false;
- send_id(c);
+ send_id(mesh, c);
}
static void do_outgoing_pipe(meshlink_handle_t *mesh, connection_t *c, char *command) {
c->outcompression = mesh->self->connection->outcompression;
c->last_ping_time = mesh->loop.now.tv_sec;
- connection_add(c);
+ connection_add(mesh, c);
io_add(&mesh->loop, &c->io, handle_meta_io, c, c->socket, IO_READ|IO_WRITE);
void setup_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) {
timeout_del(&mesh->loop, &outgoing->ev);
- node_t *n = lookup_node(outgoing->name);
+ node_t *n = lookup_node(mesh, outgoing->name);
if(n && n->connection) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", outgoing->name);
configure_tcp(c);
- connection_add(c);
+ connection_add(mesh, c);
c->allow_request = ID;
- send_id(c);
+ send_id(mesh, c);
}
static void free_outgoing(meshlink_handle_t *mesh, outgoing_t *outgoing) {
return strcmp(a->name, b->name);
}
-void init_nodes(void) {
+void init_nodes(meshlink_handle_t *mesh) {
mesh->nodes = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t));
}
-void exit_nodes(void) {
+void exit_nodes(meshlink_handle_t *mesh) {
hash_free(node_udp_cache);
splay_delete_tree(mesh->nodes);
}
ecdsa_free(n->ecdsa);
sptps_stop(&n->sptps);
- timeout_del(&mesh->loop, &n->mtutimeout);
+ if(n->mtutimeout.cb)
+ abort();
if(n->hostname)
free(n->hostname);
free(n);
}
-void node_add(node_t *n) {
+void node_add(meshlink_handle_t *mesh, node_t *n) {
+ n->mesh = mesh;
splay_insert(mesh->nodes, n);
}
-void node_del(node_t *n) {
+void node_del(meshlink_handle_t *mesh, node_t *n) {
+ timeout_del(&mesh->loop, &n->mtutimeout);
+
for splay_each(edge_t, e, n->edge_tree)
- edge_del(e);
+ edge_del(mesh, e);
splay_delete(mesh->nodes, n);
}
-node_t *lookup_node(char *name) {
+node_t *lookup_node(meshlink_handle_t *mesh, char *name) {
node_t n = {NULL};
n.name = name;
return splay_search(mesh->nodes, &n);
}
-node_t *lookup_node_udp(const sockaddr_t *sa) {
+node_t *lookup_node_udp(meshlink_handle_t *mesh, const sockaddr_t *sa) {
return hash_search(node_udp_cache, sa);
}
-void update_node_udp(node_t *n, const sockaddr_t *sa) {
+void update_node_udp(meshlink_handle_t *mesh, node_t *n, const sockaddr_t *sa) {
if(n == mesh->self) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Trying to update UDP address of mesh->self!");
return;
char *name; /* name of this node */
uint32_t options; /* options turned on for this node */
+ struct meshlink_handle *mesh; /* The mesh this node belongs to */
+
int sock; /* Socket to use for outgoing UDP packets */
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
char *hostname; /* the hostname of its real ip */
uint64_t out_bytes;
} node_t;
-extern void init_nodes(void);
-extern void exit_nodes(void);
+extern void init_nodes(struct meshlink_handle *mesh);
+extern void exit_nodes(struct meshlink_handle *mesh);
extern node_t *new_node(void) __attribute__ ((__malloc__));
extern void free_node(node_t *);
-extern void node_add(node_t *);
-extern void node_del(node_t *);
-extern node_t *lookup_node(char *);
-extern node_t *lookup_node_udp(const sockaddr_t *);
-extern void update_node_udp(node_t *, const sockaddr_t *);
+extern void node_add(struct meshlink_handle *mesh, node_t *);
+extern void node_del(struct meshlink_handle *mesh, node_t *);
+extern node_t *lookup_node(struct meshlink_handle *mesh, char *);
+extern node_t *lookup_node_udp(struct meshlink_handle *mesh, const sockaddr_t *);
+extern void update_node_udp(struct meshlink_handle *mesh, node_t *, const sockaddr_t *);
#endif /* __TINC_NODE_H__ */
/* Jumptable for the request handlers */
-static bool (*request_handlers[])(connection_t *, const char *) = {
+static bool (*request_handlers[])(meshlink_handle_t *, connection_t *, const char *) = {
id_h, NULL, NULL, NULL /* metakey_h, challenge_h, chal_reply_h */, ack_h,
status_h, error_h, termreq_h,
ping_h, pong_h,
/* Generic request routines - takes care of logging and error
detection as well */
-bool send_request(connection_t *c, const char *format, ...) {
+bool send_request(meshlink_handle_t *mesh, connection_t *c, const char *format, ...) {
va_list args;
char request[MAXBUFSIZE];
int len;
request[len++] = '\n';
if(c == mesh->everyone) {
- broadcast_meta(NULL, request, len);
+ broadcast_meta(mesh, NULL, request, len);
return true;
} else
- return send_meta(c, request, len);
+ return send_meta(mesh, c, request, len);
}
-void forward_request(connection_t *from, const char *request) {
+void forward_request(meshlink_handle_t *mesh, connection_t *from, const char *request) {
logger(DEBUG_META, LOG_DEBUG, "Forwarding %s from %s (%s): %s", request_name[atoi(request)], from->name, from->hostname, request);
// Create a temporary newline-terminated copy of the request
char tmp[len + 1];
memcpy(tmp, request, len);
tmp[len] = '\n';
- broadcast_meta(from, tmp, sizeof tmp);
+ broadcast_meta(mesh, from, tmp, sizeof tmp);
}
-bool receive_request(connection_t *c, const char *request) {
+bool receive_request(meshlink_handle_t *mesh, connection_t *c, const char *request) {
if(c->outgoing && mesh->proxytype == PROXY_HTTP && c->allow_request == ID) {
if(!request[0] || request[0] == '\r')
return true;
return false;
}
- if(!request_handlers[reqno](c, request)) {
+ if(!request_handlers[reqno](mesh, c, request)) {
/* Something went wrong. Probably scriptkiddies. Terminate. */
logger(DEBUG_ALWAYS, LOG_ERR, "Error while processing %s from %s (%s)", request_name[reqno], c->name, c->hostname);
static void free_past_request(past_request_t *r) {
if(r->request)
- free((char *)r->request);
+ free(r->request);
free(r);
}
static timeout_t past_request_timeout;
static void age_past_requests(event_loop_t *loop, void *data) {
+ meshlink_handle_t *mesh = loop->data;
int left = 0, deleted = 0;
for splay_each(past_request_t, p, past_request_tree) {
timeout_set(&mesh->loop, &past_request_timeout, &(struct timeval){10, rand() % 100000});
}
-bool seen_request(const char *request) {
+bool seen_request(meshlink_handle_t *mesh, const char *request) {
past_request_t *new, p = {NULL};
p.request = request;
}
}
-void init_requests(void) {
+// TODO: move past_request_tree to meshlink_handle_t
+void init_requests(meshlink_handle_t *mesh) {
past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request);
}
-void exit_requests(void) {
+void exit_requests(meshlink_handle_t *mesh) {
splay_delete_tree(past_request_tree);
timeout_del(&mesh->loop, &past_request_timeout);
/* Basic functions */
-extern bool send_request(struct connection_t *, const char *, ...) __attribute__ ((__format__(printf, 2, 3)));
-extern void forward_request(struct connection_t *, const char *);
-extern bool receive_request(struct connection_t *, const char *);
+extern bool send_request(struct meshlink_handle *mesh, struct connection_t *, const char *, ...) __attribute__ ((__format__(printf, 3, 4)));
+extern void forward_request(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool receive_request(struct meshlink_handle *mesh, struct connection_t *, const char *);
extern bool check_id(const char *);
-extern void init_requests(void);
-extern void exit_requests(void);
-extern bool seen_request(const char *);
+extern void init_requests(struct meshlink_handle *mesh);
+extern void exit_requests(struct meshlink_handle *mesh);
+extern bool seen_request(struct meshlink_handle *mesh, const char *);
/* Requests */
-extern bool send_id(struct connection_t *);
-extern bool send_ack(struct connection_t *);
-extern bool send_status(struct connection_t *, int, const char *);
-extern bool send_error(struct connection_t *, int, const char *);
-extern bool send_termreq(struct connection_t *);
-extern bool send_ping(struct connection_t *);
-extern bool send_pong(struct connection_t *);
-extern bool send_add_edge(struct connection_t *, const struct edge_t *);
-extern bool send_del_edge(struct connection_t *, const struct edge_t *);
-extern void send_key_changed(void);
-extern bool send_req_key(struct node_t *);
-extern bool send_ans_key(struct node_t *);
-extern bool send_tcppacket(struct connection_t *, const struct vpn_packet_t *);
+extern bool send_id(struct meshlink_handle *mesh, struct connection_t *);
+extern bool send_ack(struct meshlink_handle *mesh, struct connection_t *);
+extern bool send_status(struct meshlink_handle *mesh, struct connection_t *, int, const char *);
+extern bool send_error(struct meshlink_handle *mesh, struct connection_t *, int, const char *);
+extern bool send_termreq(struct meshlink_handle *mesh, struct connection_t *);
+extern bool send_ping(struct meshlink_handle *mesh, struct connection_t *);
+extern bool send_pong(struct meshlink_handle *mesh, struct connection_t *);
+extern bool send_add_edge(struct meshlink_handle *mesh, struct connection_t *, const struct edge_t *);
+extern bool send_del_edge(struct meshlink_handle *mesh, struct connection_t *, const struct edge_t *);
+extern void send_key_changed(struct meshlink_handle *mesh);
+extern bool send_req_key(struct meshlink_handle *mesh, struct node_t *);
+extern bool send_ans_key(struct meshlink_handle *mesh, struct node_t *);
+extern bool send_tcppacket(struct meshlink_handle *mesh, struct connection_t *, const struct vpn_packet_t *);
/* Request handlers */
-extern bool id_h(struct connection_t *, const char *);
-extern bool ack_h(struct connection_t *, const char *);
-extern bool status_h(struct connection_t *, const char *);
-extern bool error_h(struct connection_t *, const char *);
-extern bool termreq_h(struct connection_t *, const char *);
-extern bool ping_h(struct connection_t *, const char *);
-extern bool pong_h(struct connection_t *, const char *);
-extern bool add_edge_h(struct connection_t *, const char *);
-extern bool del_edge_h(struct connection_t *, const char *);
-extern bool key_changed_h(struct connection_t *, const char *);
-extern bool req_key_h(struct connection_t *, const char *);
-extern bool ans_key_h(struct connection_t *, const char *);
-extern bool tcppacket_h(struct connection_t *, const char *);
+extern bool id_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool ack_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool status_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool error_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool termreq_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool ping_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool pong_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool add_edge_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool del_edge_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool key_changed_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool req_key_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool ans_key_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+extern bool tcppacket_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
#endif /* __TINC_PROTOCOL_H__ */
#include "xalloc.h"
#include "ed25519/sha512.h"
-static bool send_proxyrequest(connection_t *c) {
+static bool send_proxyrequest(meshlink_handle_t *mesh, connection_t *c) {
switch(mesh->proxytype) {
case PROXY_HTTP: {
char *host;
char *port;
sockaddr2str(&c->address, &host, &port);
- send_request(c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port);
+ send_request(mesh, c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port);
free(host);
free(port);
return true;
memcpy(s4req + 8, mesh->proxyuser, strlen(mesh->proxyuser));
s4req[sizeof s4req - 1] = 0;
c->tcplen = 8;
- return send_meta(c, s4req, sizeof s4req);
+ return send_meta(mesh, c, s4req, sizeof s4req);
}
case PROXY_SOCKS5: {
int len = 3 + 6 + (c->address.sa.sa_family == AF_INET ? 4 : 16);
}
if(i > len)
abort();
- return send_meta(c, s5req, sizeof s5req);
+ return send_meta(mesh, c, s5req, sizeof s5req);
}
case PROXY_SOCKS4A:
logger(DEBUG_ALWAYS, LOG_ERR, "Proxy type not implemented yet");
}
}
-bool send_id(connection_t *c) {
+bool send_id(meshlink_handle_t *mesh, connection_t *c) {
gettimeofday(&c->start, NULL);
int minor = mesh->self->connection->protocol_minor;
if(mesh->proxytype && c->outgoing)
- if(!send_proxyrequest(c))
+ if(!send_proxyrequest(mesh, c))
return false;
- return send_request(c, "%d %s %d.%d", ID, mesh->self->connection->name, mesh->self->connection->protocol_major, minor);
+ return send_request(mesh, c, "%d %s %d.%d", ID, mesh->self->connection->name, mesh->self->connection->protocol_major, minor);
}
-static bool finalize_invitation(connection_t *c, const char *data, uint16_t len) {
+static bool finalize_invitation(meshlink_handle_t *mesh, connection_t *c, const char *data, uint16_t len) {
if(strchr(data, '\n')) {
logger(DEBUG_ALWAYS, LOG_ERR, "Received invalid key from invited node %s (%s)!\n", c->name, c->hostname);
return false;
static bool receive_invitation_sptps(void *handle, uint8_t type, const char *data, uint16_t len) {
connection_t *c = handle;
+ meshlink_handle_t *mesh = c->mesh;
if(type == 128)
return true;
if(type == 1 && c->status.invitation_used)
- return finalize_invitation(c, data, len);
+ return finalize_invitation(mesh, c, data, len);
if(type != 0 || len != 18 || c->status.invitation_used)
return false;
return true;
}
-bool id_h(connection_t *c, const char *request) {
+bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
char name[MAX_STRING_SIZE];
if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) {
char *mykey = ecdsa_get_base64_public_key(mesh->invitation_key);
if(!mykey)
return false;
- if(!send_request(c, "%d %s", ACK, mykey))
+ if(!send_request(mesh, c, "%d %s", ACK, mykey))
return false;
free(mykey);
return sptps_start(&c->sptps, c, c->outgoing, false, mesh->self->connection->ecdsa, c->ecdsa, label, sizeof label, send_meta_sptps, receive_meta_sptps);
}
-bool send_ack(connection_t *c) {
+bool send_ack(meshlink_handle_t *mesh, connection_t *c) {
/* ACK message contains rest of the information the other end needs
to create node_t and edge_t structures. */
if(mesh->self->options & OPTION_PMTU_DISCOVERY)
c->options |= OPTION_PMTU_DISCOVERY;
- return send_request(c, "%d %s %d %x", ACK, mesh->myport, c->estimated_weight, (c->options & 0xffffff) | (PROT_MINOR << 24));
+ return send_request(mesh, c, "%d %s %d %x", ACK, mesh->myport, c->estimated_weight, (c->options & 0xffffff) | (PROT_MINOR << 24));
}
-static void send_everything(connection_t *c) {
+static void send_everything(meshlink_handle_t *mesh, connection_t *c) {
/* Send all known subnets and edges */
for splay_each(node_t, n, mesh->nodes) {
for splay_each(edge_t, e, n->edge_tree)
- send_add_edge(c, e);
+ send_add_edge(mesh, c, e);
}
}
-bool ack_h(connection_t *c, const char *request) {
+bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
char hisport[MAX_STRING_SIZE];
char *hisaddress;
int weight, mtu;
/* Check if we already have a node_t for him */
- n = lookup_node(c->name);
+ n = lookup_node(mesh, c->name);
if(!n) {
n = new_node();
n->name = xstrdup(c->name);
- node_add(n);
+ node_add(mesh, n);
} else {
if(n->connection) {
/* Oh dear, we already have a connection to this node. */
terminate_connection(mesh, n->connection, false);
/* Run graph algorithm to keep things in sync */
- graph();
+ graph(mesh);
}
}
/* Send him everything we know */
- send_everything(c);
+ send_everything(mesh, c);
/* Create an edge_t for this connection */
c->edge->connection = c;
c->edge->options = c->options;
- edge_add(c->edge);
+ edge_add(mesh, c->edge);
/* Notify everyone of the new edge */
- send_add_edge(mesh->everyone, c->edge);
+ send_add_edge(mesh, mesh->everyone, c->edge);
/* Run MST and SSSP algorithms */
- graph();
+ graph(mesh);
return true;
}
#include "utils.h"
#include "xalloc.h"
-bool send_add_edge(connection_t *c, const edge_t *e) {
+bool send_add_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e) {
bool x;
char *address, *port;
sockaddr2str(&e->address, &address, &port);
- x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(),
+ x = send_request(mesh, c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(),
e->from->name, e->to->name, address, port,
e->options, e->weight);
free(address);
return x;
}
-bool add_edge_h(connection_t *c, const char *request) {
+bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
edge_t *e;
node_t *from, *to;
char from_name[MAX_STRING_SIZE];
return false;
}
- if(seen_request(request))
+ if(seen_request(mesh, request))
return true;
/* Lookup nodes */
- from = lookup_node(from_name);
- to = lookup_node(to_name);
+ from = lookup_node(mesh, from_name);
+ to = lookup_node(mesh, to_name);
if(!from) {
from = new_node();
from->name = xstrdup(from_name);
- node_add(from);
+ node_add(mesh, from);
}
if(!to) {
to = new_node();
to->name = xstrdup(to_name);
- node_add(to);
+ node_add(mesh, to);
}
if(from == mesh->self) {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
"ADD_EDGE", c->name, c->hostname);
- send_add_edge(c, e);
+ send_add_edge(mesh, c, e);
return true;
} else {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not match existing entry",
"ADD_EDGE", c->name, c->hostname);
- edge_del(e);
- graph();
+ edge_del(mesh, e);
+ graph(mesh);
}
} else
return true;
e = new_edge();
e->from = from;
e->to = to;
- send_del_edge(c, e);
+ send_del_edge(mesh, c, e);
free_edge(e);
return true;
}
e->address = address;
e->options = options;
e->weight = weight;
- edge_add(e);
+ edge_add(mesh, e);
/* Tell the rest about the new edge */
- forward_request(c, request);
+ forward_request(mesh, c, request);
/* Run MST before or after we tell the rest? */
- graph();
+ graph(mesh);
return true;
}
-bool send_del_edge(connection_t *c, const edge_t *e) {
- return send_request(c, "%d %x %s %s", DEL_EDGE, rand(),
+bool send_del_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e) {
+ return send_request(mesh, c, "%d %x %s %s", DEL_EDGE, rand(),
e->from->name, e->to->name);
}
-bool del_edge_h(connection_t *c, const char *request) {
+bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
edge_t *e;
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
return false;
}
- if(seen_request(request))
+ if(seen_request(mesh, request))
return true;
/* Lookup nodes */
- from = lookup_node(from_name);
- to = lookup_node(to_name);
+ from = lookup_node(mesh, from_name);
+ to = lookup_node(mesh, to_name);
if(!from) {
logger(DEBUG_PROTOCOL, LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree",
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself",
"DEL_EDGE", c->name, c->hostname);
mesh->contradicting_del_edge++;
- send_add_edge(c, e); /* Send back a correction */
+ send_add_edge(mesh, c, e); /* Send back a correction */
return true;
}
/* Tell the rest about the deleted edge */
- forward_request(c, request);
+ forward_request(mesh, c, request);
/* Delete the edge */
- edge_del(e);
+ edge_del(mesh, e);
/* Run MST before or after we tell the rest? */
- graph();
+ graph(mesh);
/* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
if(!to->status.reachable) {
e = lookup_edge(to, mesh->self);
if(e) {
- send_del_edge(mesh->everyone, e);
- edge_del(e);
+ send_del_edge(mesh, mesh->everyone, e);
+ edge_del(mesh, e);
}
}
static bool mykeyused = false;
-void send_key_changed(void) {
- send_request(mesh->everyone, "%d %x %s", KEY_CHANGED, rand(), mesh->self->name);
+void send_key_changed(meshlink_handle_t *mesh) {
+ send_request(mesh, mesh->everyone, "%d %x %s", KEY_CHANGED, rand(), mesh->self->name);
/* Force key exchange for connections using SPTPS */
sptps_force_kex(&n->sptps);
}
-bool key_changed_h(connection_t *c, const char *request) {
+bool key_changed_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
char name[MAX_STRING_SIZE];
node_t *n;
return false;
}
- if(seen_request(request))
+ if(seen_request(mesh, request))
return true;
- n = lookup_node(name);
+ n = lookup_node(mesh, name);
if(!n) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
/* Tell the others */
- forward_request(c, request);
+ forward_request(mesh, c, request);
return true;
}
static bool send_initial_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
node_t *to = handle;
+ meshlink_handle_t *mesh = to->mesh;
to->sptps.send_data = send_sptps_data;
char buf[len * 4 / 3 + 5];
b64encode(data, buf, len);
- return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_KEY, buf);
+ return send_request(mesh, to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_KEY, buf);
}
-bool send_req_key(node_t *to) {
+bool send_req_key(meshlink_handle_t *mesh, node_t *to) {
if(!node_read_ecdsa_public_key(mesh, to)) {
logger(DEBUG_PROTOCOL, LOG_DEBUG, "No ECDSA key known for %s (%s)", to->name, to->hostname);
- send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, mesh->self->name, to->name, REQ_PUBKEY);
+ send_request(mesh, to->nexthop->connection, "%d %s %s %d", REQ_KEY, mesh->self->name, to->name, REQ_PUBKEY);
return true;
}
/* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
-static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, int reqno) {
+static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char *request, node_t *from, int reqno) {
switch(reqno) {
case REQ_PUBKEY: {
char *pubkey = ecdsa_get_base64_public_key(mesh->self->connection->ecdsa);
- send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, from->name, ANS_PUBKEY, pubkey);
+ send_request(mesh, from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, from->name, ANS_PUBKEY, pubkey);
free(pubkey);
return true;
}
case REQ_KEY: {
if(!node_read_ecdsa_public_key(mesh, from)) {
logger(DEBUG_PROTOCOL, LOG_DEBUG, "No ECDSA key known for %s (%s)", from->name, from->hostname);
- send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, mesh->self->name, from->name, REQ_PUBKEY);
+ send_request(mesh, from->nexthop->connection, "%d %s %s %d", REQ_KEY, mesh->self->name, from->name, REQ_PUBKEY);
return true;
}
}
}
-bool req_key_h(connection_t *c, const char *request) {
+bool req_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
node_t *from, *to;
return false;
}
- from = lookup_node(from_name);
+ from = lookup_node(mesh, from_name);
if(!from) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
return true;
}
- to = lookup_node(to_name);
+ to = lookup_node(mesh, to_name);
if(!to) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
if(to == mesh->self) { /* Yes */
/* Is this an extended REQ_KEY message? */
if(reqno)
- return req_key_ext_h(c, request, from, reqno);
+ return req_key_ext_h(mesh, c, request, from, reqno);
/* No, just send our key back */
- send_ans_key(from);
+ send_ans_key(mesh, from);
} else {
if(!to->status.reachable) {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
return true;
}
- send_request(to->nexthop->connection, "%s", request);
+ send_request(mesh, to->nexthop->connection, "%s", request);
}
return true;
}
-bool send_ans_key(node_t *to) {
+bool send_ans_key(meshlink_handle_t *mesh, node_t *to) {
abort();
}
-bool ans_key_h(connection_t *c, const char *request) {
+bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
char key[MAX_STRING_SIZE];
return false;
}
- from = lookup_node(from_name);
+ from = lookup_node(mesh, from_name);
if(!from) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
return true;
}
- to = lookup_node(to_name);
+ to = lookup_node(mesh, to_name);
if(!to) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
char *address, *port;
logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
sockaddr2str(&from->address, &address, &port);
- send_request(to->nexthop->connection, "%s %s %s", request, address, port);
+ send_request(mesh, to->nexthop->connection, "%s %s %s", request, address, port);
free(address);
free(port);
return true;
}
- return send_request(to->nexthop->connection, "%s", request);
+ return send_request(mesh, to->nexthop->connection, "%s", request);
}
/* Don't use key material until every check has passed. */
if(*address && *port) {
logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
sockaddr_t sa = str2sockaddr(address, port);
- update_node_udp(from, &sa);
+ update_node_udp(mesh, from, &sa);
}
if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY))
/* Status and error notification routines */
-bool send_status(connection_t *c, int statusno, const char *statusstring) {
+bool send_status(meshlink_handle_t *mesh, connection_t *c, int statusno, const char *statusstring) {
if(!statusstring)
statusstring = "Status";
- return send_request(c, "%d %d %s", STATUS, statusno, statusstring);
+ return send_request(mesh, c, "%d %d %s", STATUS, statusno, statusstring);
}
-bool status_h(connection_t *c, const char *request) {
+bool status_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
int statusno;
char statusstring[MAX_STRING_SIZE];
return true;
}
-bool send_error(connection_t *c, int err, const char *errstring) {
+bool send_error(meshlink_handle_t *mesh, connection_t *c, int err, const char *errstring) {
if(!errstring)
errstring = "Error";
- return send_request(c, "%d %d %s", ERROR, err, errstring);
+ return send_request(mesh, c, "%d %d %s", ERROR, err, errstring);
}
-bool error_h(connection_t *c, const char *request) {
+bool error_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
int err;
char errorstring[MAX_STRING_SIZE];
return false;
}
-bool send_termreq(connection_t *c) {
- return send_request(c, "%d", TERMREQ);
+bool send_termreq(meshlink_handle_t *mesh, connection_t *c) {
+ return send_request(mesh, c, "%d", TERMREQ);
}
-bool termreq_h(connection_t *c, const char *request) {
+bool termreq_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
return false;
}
-bool send_ping(connection_t *c) {
+bool send_ping(meshlink_handle_t *mesh, connection_t *c) {
c->status.pinged = true;
c->last_ping_time = mesh->loop.now.tv_sec;
- return send_request(c, "%d", PING);
+ return send_request(mesh, c, "%d", PING);
}
-bool ping_h(connection_t *c, const char *request) {
- return send_pong(c);
+bool ping_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
+ return send_pong(mesh, c);
}
-bool send_pong(connection_t *c) {
- return send_request(c, "%d", PONG);
+bool send_pong(meshlink_handle_t *mesh, connection_t *c) {
+ return send_request(mesh, c, "%d", PONG);
}
-bool pong_h(connection_t *c, const char *request) {
+bool pong_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
c->status.pinged = false;
/* Succesful connection, reset timeout if this is an outgoing connection. */
/* Sending and receiving packets via TCP */
-bool send_tcppacket(connection_t *c, const vpn_packet_t *packet) {
+bool send_tcppacket(meshlink_handle_t *mesh, connection_t *c, const vpn_packet_t *packet) {
/* If there already is a lot of data in the outbuf buffer, discard this packet.
We use a very simple Random Early Drop algorithm. */
if(2.0 * c->outbuf.len / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX)
return true;
- if(!send_request(c, "%d %hd", PACKET, packet->len))
+ if(!send_request(mesh, c, "%d %hd", PACKET, packet->len))
return false;
- return send_meta(c, (char *)packet->data, packet->len);
+ return send_meta(mesh, c, (char *)packet->data, packet->len);
}
-bool tcppacket_h(connection_t *c, const char *request) {
+bool tcppacket_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
short int len;
if(sscanf(request, "%*d %hd", &len) != 1) {
bool decrement_ttl = false;
-static bool ratelimit(int frequency) {
- static time_t lasttime = 0;
- static int count = 0;
-
- if(lasttime == mesh->loop.now.tv_sec) {
- if(count >= frequency)
- return true;
- } else {
- lasttime = mesh->loop.now.tv_sec;
- count = 0;
- }
-
- count++;
- return false;
-}
-
static bool checklength(node_t *source, vpn_packet_t *packet, uint16_t length) {
if(packet->len < length) {
logger(DEBUG_TRAFFIC, LOG_WARNING, "Got too short packet from %s (%s)", source->name, source->hostname);
return true;
}
-void route(node_t *source,vpn_packet_t *packet) {
+void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) {
// TODO: route on name or key
node_t* owner = NULL;
node_t* via = NULL;
meshlink_packethdr_t* hdr = (meshlink_packethdr_t*)packet->data;
- owner = lookup_node(hdr->destination);
+ owner = lookup_node(mesh, hdr->destination);
logger(DEBUG_TRAFFIC, LOG_WARNING, "Routing packet from: %s . To: %s \n",hdr->source,hdr->destination);
//Check Lenght
extern bool decrement_ttl;
-extern void route(struct node_t *, struct vpn_packet_t *);
+extern void route(struct meshlink_handle *mesh, struct node_t *, struct vpn_packet_t *);
#endif /* __TINC_ROUTE_H__ */