From: Guus Sliepen Date: Sun, 13 Jun 2021 21:58:54 +0000 (+0200) Subject: Remove graph, edges and communication via UDP. X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=d0bf55f32b407fa153dd5d6e41ccefcbb4072611;p=meshlink-tiny Remove graph, edges and communication via UDP. --- diff --git a/src/Makefile.am b/src/Makefile.am index 8d62492..51a42e9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,19 +42,15 @@ libmeshlink_tiny_la_SOURCES = \ conf.c conf.h \ connection.c connection.h \ crypto.c crypto.h \ - discovery.c discovery.h \ dropin.c dropin.h \ ecdh.h \ ecdsa.h \ ecdsagen.h \ - edge.c edge.h \ event.c event.h \ - graph.c graph.h \ hash.c hash.h \ have.h \ list.c list.h \ logger.c logger.h \ - mdns.c mdns.h \ meshlink.c meshlink-tiny.h meshlink.sym \ meshlink_internal.h \ meshlink_queue.h \ diff --git a/src/connection.h b/src/connection.h index b5ccaed..248f806 100644 --- a/src/connection.h +++ b/src/connection.h @@ -44,7 +44,6 @@ typedef struct connection_status_t { } connection_status_t; #include "ecdsa.h" -#include "edge.h" #include "net.h" #include "node.h" #include "submesh.h" @@ -71,7 +70,6 @@ typedef struct connection_t { struct outgoing_t *outgoing; /* used to keep track of outgoing connections */ - struct edge_t *edge; /* edge associated with this connection */ struct submesh_t *submesh; /* his submesh handle if available in invitation file */ // Only used during authentication diff --git a/src/devtools.c b/src/devtools.c index 2a98e59..d14d1d8 100644 --- a/src/devtools.c +++ b/src/devtools.c @@ -55,210 +55,6 @@ void (*devtool_set_inviter_commits_first)(bool inviter_commited_first) = inviter void (*devtool_adns_resolve_probe)(void) = nop_probe; void (*devtool_sptps_renewal_probe)(meshlink_node_t *node) = sptps_renewal_nop_probe; -/* Return an array of edges in the current network graph. - * Data captures the current state and will not be updated. - * Caller must deallocate data when done. - */ -devtool_edge_t *devtool_get_all_edges(meshlink_handle_t *mesh, devtool_edge_t *edges, size_t *nmemb) { - if(!mesh || !nmemb || (*nmemb && !edges)) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - devtool_edge_t *result = NULL; - unsigned int result_size = 0; - - result_size = mesh->edges->count / 2; - - // if result is smaller than edges, we have to dealloc all the excess devtool_edge_t - if((size_t)result_size > *nmemb) { - result = xrealloc(edges, result_size * sizeof(*result)); - } else { - result = edges; - } - - if(result) { - devtool_edge_t *p = result; - unsigned int n = 0; - - for splay_each(edge_t, e, mesh->edges) { - // skip edges that do not represent a two-directional connection - if(!e->reverse || e->reverse->to != e->from) { - continue; - } - - // don't count edges twice - if(e->to < e->from) { - continue; - } - - assert(n < result_size); - - p->from = (meshlink_node_t *)e->from; - p->to = (meshlink_node_t *)e->to; - p->address = e->address.storage; - p->weight = e->weight; - - n++; - p++; - } - - // shrink result to the actual amount of memory used - result = xrealloc(result, n * sizeof(*result)); - *nmemb = n; - } else { - *nmemb = 0; - meshlink_errno = MESHLINK_ENOMEM; - } - - pthread_mutex_unlock(&mesh->mutex); - - return result; -} - -static bool fstrwrite(const char *str, FILE *stream) { - assert(stream); - - size_t len = strlen(str); - - if(fwrite((void *)str, 1, len, stream) != len) { - return false; - } - - return true; -} - -bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream) { - assert(stream); - - bool result = true; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - // export edges and nodes - size_t node_count = 0; - size_t edge_count = 0; - - meshlink_node_t **nodes = meshlink_get_all_nodes(mesh, NULL, &node_count); - devtool_edge_t *edges = devtool_get_all_edges(mesh, NULL, &edge_count); - - if((!nodes && node_count != 0) || (!edges && edge_count != 0)) { - goto fail; - } - - // export begin - if(!fstrwrite("{\n", stream)) { - goto fail; - } - - // export nodes - if(!fstrwrite("\t\"nodes\": {\n", stream)) { - goto fail; - } - - char buf[16]; - - for(size_t i = 0; i < node_count; ++i) { - if(!fstrwrite("\t\t\"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\": {\n", stream)) { - goto fail; - } - - if(!fstrwrite("\t\t\t\"name\": \"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\",\n", stream)) { - goto fail; - } - - snprintf(buf, sizeof(buf), "%d", ((node_t *)nodes[i])->devclass); - - if(!fstrwrite("\t\t\t\"devclass\": ", stream) || !fstrwrite(buf, stream) || !fstrwrite("\n", stream)) { - goto fail; - } - - if(!fstrwrite((i + 1) != node_count ? "\t\t},\n" : "\t\t}\n", stream)) { - goto fail; - } - } - - if(!fstrwrite("\t},\n", stream)) { - goto fail; - } - - // export edges - - if(!fstrwrite("\t\"edges\": {\n", stream)) { - goto fail; - } - - for(size_t i = 0; i < edge_count; ++i) { - if(!fstrwrite("\t\t\"", stream) || !fstrwrite(edges[i].from->name, stream) || !fstrwrite("_to_", stream) || !fstrwrite(edges[i].to->name, stream) || !fstrwrite("\": {\n", stream)) { - goto fail; - } - - if(!fstrwrite("\t\t\t\"from\": \"", stream) || !fstrwrite(edges[i].from->name, stream) || !fstrwrite("\",\n", stream)) { - goto fail; - } - - if(!fstrwrite("\t\t\t\"to\": \"", stream) || !fstrwrite(edges[i].to->name, stream) || !fstrwrite("\",\n", stream)) { - goto fail; - } - - char *host = NULL, *port = NULL, *address = NULL; - sockaddr2str((const sockaddr_t *)&edges[i].address, &host, &port); - - if(host && port) { - xasprintf(&address, "{ \"host\": \"%s\", \"port\": %s }", host, port); - } - - free(host); - free(port); - - if(!fstrwrite("\t\t\t\"address\": ", stream) || !fstrwrite(address ? address : "null", stream) || !fstrwrite(",\n", stream)) { - free(address); - goto fail; - } - - free(address); - - snprintf(buf, sizeof(buf), "%d", edges[i].weight); - - if(!fstrwrite("\t\t\t\"weight\": ", stream) || !fstrwrite(buf, stream) || !fstrwrite("\n", stream)) { - goto fail; - } - - if(!fstrwrite((i + 1) != edge_count ? "\t\t},\n" : "\t\t}\n", stream)) { - goto fail; - } - } - - if(!fstrwrite("\t}\n", stream)) { - goto fail; - } - - // DONE! - - if(!fstrwrite("}", stream)) { - goto fail; - } - - goto done; - -fail: - result = false; - -done: - free(nodes); - free(edges); - - pthread_mutex_unlock(&mesh->mutex); - - return result; -} - void devtool_get_node_status(meshlink_handle_t *mesh, meshlink_node_t *node, devtool_node_status_t *status) { if(!mesh || !node || !status) { meshlink_errno = MESHLINK_EINVAL; diff --git a/src/devtools.h b/src/devtools.h index 786e290..c9335cf 100644 --- a/src/devtools.h +++ b/src/devtools.h @@ -26,61 +26,6 @@ * Applications should not depend on any of these functions for their normal operation. */ -/// An edge in the MeshLink network. -typedef struct devtool_edge devtool_edge_t; - -/// An edge in the MeshLink network. -struct devtool_edge { - struct meshlink_node *from; ///< Pointer to a node. Node memory is - // owned by meshlink and should not be - // deallocated. Node contents may be - // changed by meshlink. - struct meshlink_node *to; ///< Pointer to a node. Node memory is - // owned by meshlink and should not be - // deallocated. Node contents may be - // changed by meshlink. - struct sockaddr_storage address;///< The address information associated - // with this edge. - int weight; ///< Weight assigned to this edge. -}; - -/// Get a list of edges. -/** This function returns an array with copies of all known bidirectional edges. - * The edges are copied to capture the mesh state at call time, since edges - * mutate frequently. The nodes pointed to within the devtool_edge_t type - * are not copies; these are the same pointers that one would get from a call - * to meshlink_get_all_nodes(). - * - * @param mesh A handle which represents an instance of MeshLink. - * @param edges A pointer to a previously allocated array of - * devtool_edge_t, or NULL in which case MeshLink will - * allocate a new array. - * The application is allowed to call free() on the array whenever it wishes. - * The pointers in the devtool_edge_t elements are valid until - * meshlink_close() is called. - * @param nmemb A pointer to a variable holding the number of elements that - * are stored in the array. In case the @a edges @a - * argument is not NULL, MeshLink might call realloc() - * on the array to change its size. - * The contents of this variable will be changed to reflect - * the new size of the array. - * @return A pointer to an array containing devtool_edge_t elements, - * or NULL in case of an error. - * If the @a edges @a argument was not NULL, then the - * return value can be either the same value or a different - * value. If the new values is NULL, then the old array - * will have been freed by Meshlink. - */ -devtool_edge_t *devtool_get_all_edges(meshlink_handle_t *mesh, devtool_edge_t *edges, size_t *nmemb); - -/// Export a list of edges to a file in JSON format. -/* @param mesh A handle which represents an instance of MeshLink. - * @param FILE An open file descriptor to which a JSON representation of the edges will be written. - * - * @return True in case of success, false otherwise. - */ -bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream); - /// The status of a node. typedef struct devtool_node_status devtool_node_status_t; diff --git a/src/discovery.c b/src/discovery.c deleted file mode 100644 index 032b559..0000000 --- a/src/discovery.c +++ /dev/null @@ -1,1063 +0,0 @@ -/* - discovery.c -- local network discovery - Copyright (C) 2014-2021 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#define __APPLE_USE_RFC_3542 -#include "system.h" - -#if defined(__APPLE__) -#include -#include -#include -#include -#include -#include -#elif defined(__unix) && !defined(__linux) -#include -#include -#include -#elif defined(__linux) -#include -#include -#include -#include -#include -#endif - -#include "mdns.h" -#include "meshlink_internal.h" -#include "event.h" -#include "discovery.h" -#include "sockaddr.h" -#include "logger.h" -#include "netutl.h" -#include "node.h" -#include "connection.h" -#include "utils.h" -#include "xalloc.h" - -#define MESHLINK_MDNS_SERVICE_TYPE "_%s._tcp" -#define MESHLINK_MDNS_NAME_KEY "name" -#define MESHLINK_MDNS_FINGERPRINT_KEY "fingerprint" - -#ifndef MSG_NOSIGNAL -#define MSG_NOSIGNAL 0 -#endif - -#ifndef IPV6_ADD_MEMBERSHIP -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#endif - -#ifndef IPV6_DROP_MEMBERSHIP -#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -#endif - -static const sockaddr_t mdns_address_ipv4 = { - .in.sin_family = AF_INET, - .in.sin_addr.s_addr = 0xfb0000e0, - .in.sin_port = 0xe914, -}; - -static const sockaddr_t mdns_address_ipv6 = { - .in6.sin6_family = AF_INET6, - .in6.sin6_addr.s6_addr[0x0] = 0xff, - .in6.sin6_addr.s6_addr[0x1] = 0x02, - .in6.sin6_addr.s6_addr[0xf] = 0xfb, - .in6.sin6_port = 0xe914, -}; - -typedef struct discovery_address { - int index; - bool up; - sockaddr_t address; - time_t last_response_sent; -} discovery_address_t; - -static int iface_compare(const void *va, const void *vb) { - const int *a = va; - const int *b = vb; - return *a - *b; -} - -static int address_compare(const void *va, const void *vb) { - const discovery_address_t *a = va; - const discovery_address_t *b = vb; - - if(a->index != b->index) { - return a->index - b->index; - } - - return sockaddrcmp_noport(&a->address, &b->address); -} - -static void send_mdns_packet_ipv4(meshlink_handle_t *mesh, int fd, int index, const sockaddr_t *src, const sockaddr_t *dest, void *data, size_t len) { -#ifdef IP_MULTICAST_IF - struct ip_mreqn mreq = { - .imr_address = src->in.sin_addr, - .imr_ifindex = index, - }; - - if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)) != 0) { - logger(mesh, MESHLINK_ERROR, "Could not set outgoing multicast interface on IPv4 socket"); - return; - } - -#endif - -#ifdef IP_PKTINFO - struct iovec iov = { - .iov_base = data, - .iov_len = len, - }; - - struct in_pktinfo pkti = { - .ipi_ifindex = index, - .ipi_addr = src->in.sin_addr, - }; - - union { - char buf[CMSG_SPACE(sizeof(pkti))]; - struct cmsghdr align; - } u; - - memset(&u, 0, sizeof(u)); - - struct msghdr msg = { - .msg_name = (struct sockaddr *) &dest->sa, - .msg_namelen = SALEN(dest->sa), - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = u.buf, - .msg_controllen = sizeof(u.buf), - }; - - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = IPPROTO_IP; - cmsg->cmsg_type = IP_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(pkti)); - memcpy(CMSG_DATA(cmsg), &pkti, sizeof(pkti)); - - // Send the packet - ssize_t result = sendmsg(fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL); -#else - (void)index; - (void)src; - - // Send the packet - ssize_t result = sendto(fd, data, len, MSG_DONTWAIT | MSG_NOSIGNAL, &dest->sa, SALEN(dest->sa)); -#endif - - if(result <= 0) { - logger(mesh, MESHLINK_ERROR, "Error sending multicast packet: %s", strerror(errno)); - } -} - -static void send_mdns_packet_ipv6(meshlink_handle_t *mesh, int fd, int index, const sockaddr_t *src, const sockaddr_t *dest, void *data, size_t len) { -#ifdef IPV6_MULTICAST_IF - - if(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) != 0) { - logger(mesh, MESHLINK_ERROR, "Could not set outgoing multicast interface on IPv6 socket"); - return; - } - -#endif - -#ifdef IPV6_PKTINFO - struct iovec iov = { - .iov_base = data, - .iov_len = len, - }; - - struct in6_pktinfo pkti = { - .ipi6_ifindex = index, - .ipi6_addr = src->in6.sin6_addr, - }; - - union { - char buf[CMSG_SPACE(sizeof(pkti))]; - struct cmsghdr align; - } u; - - memset(&u, 0, sizeof u); - - struct msghdr msg = { - .msg_name = (struct sockaddr *) &dest->sa, - .msg_namelen = SALEN(dest->sa), - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = u.buf, - .msg_controllen = CMSG_LEN(sizeof(pkti)), - }; - - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = IPPROTO_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(pkti)); - memcpy(CMSG_DATA(cmsg), &pkti, sizeof(pkti)); - - // Send the packet - ssize_t result = sendmsg(fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL); -#else - (void)index; - (void)src; - - // Send the packet - ssize_t result = sendto(fd, data, len, MSG_DONTWAIT | MSG_NOSIGNAL, &dest->sa, SALEN(dest->sa)); -#endif - - if(result <= 0) { - logger(mesh, MESHLINK_ERROR, "Error sending multicast packet: %s", strerror(errno)); - } -} - -static void send_mdns_packet(meshlink_handle_t *mesh, discovery_address_t *addr, bool response) { - // Configure the socket to send the packet to the right interface - uint8_t msg[1024]; - size_t msg_size; - - if(response) { - char *fingerprint = meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self); - static const char *keys[] = {MESHLINK_MDNS_NAME_KEY, MESHLINK_MDNS_FINGERPRINT_KEY}; - const char *values[] = {mesh->name, fingerprint}; - msg_size = prepare_response(msg, sizeof msg, fingerprint, mesh->appname, "tcp", atoi(mesh->myport), 2, keys, values); - free(fingerprint); - addr->last_response_sent = mesh->loop.now.tv_sec; - } else { - msg_size = prepare_request(msg, sizeof msg, mesh->appname, "tcp"); - } - - switch(addr->address.sa.sa_family) { - case AF_INET: - send_mdns_packet_ipv4(mesh, mesh->discovery.sockets[0].fd, addr->index, &addr->address, &mdns_address_ipv4, msg, msg_size); - break; - - case AF_INET6: - send_mdns_packet_ipv6(mesh, mesh->discovery.sockets[1].fd, addr->index, &addr->address, &mdns_address_ipv6, msg, msg_size); - break; - - default: - break; - } -} - -static void mdns_io_handler(event_loop_t *loop, void *data, int flags) { - (void)flags; - meshlink_handle_t *mesh = loop->data; - io_t *io = data; - uint8_t buf[1024]; - sockaddr_t sa; - socklen_t sl = sizeof(sa); - -#ifdef IP_PKTINFO - struct iovec iov = { - .iov_base = buf, - .iov_len = sizeof(buf), - }; - - union { - char buf[1024]; - struct cmsghdr align; - } u; - - struct msghdr msg = { - .msg_name = &sa, - .msg_namelen = sl, - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = u.buf, - .msg_controllen = sizeof(u.buf), - }; - - ssize_t len = recvmsg(io->fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL); - - sl = msg.msg_namelen; -#else - ssize_t len = recvfrom(io->fd, buf, sizeof(buf), MSG_DONTWAIT, &sa.sa, &sl); -#endif - - if(len == -1) { - if(!sockwouldblock(errno)) { - logger(mesh, MESHLINK_ERROR, "Error reading from mDNS discovery socket: %s", strerror(errno)); - io_set(loop, io, 0); - } - - return; - } - - char *name = NULL; - uint16_t port = 0; - const char *keys[2] = {MESHLINK_MDNS_NAME_KEY, MESHLINK_MDNS_FINGERPRINT_KEY}; - char *values[2] = {NULL, NULL}; - - if(parse_response(buf, len, &name, mesh->appname, "tcp", &port, 2, keys, values)) { - node_t *n = (node_t *)meshlink_get_node(mesh, values[0]); - - if(n) { - if(n != mesh->self) { - logger(mesh, MESHLINK_INFO, "Node %s discovered on the local network.\n", n->name); - } - - switch(sa.sa.sa_family) { - case AF_INET: - sa.in.sin_port = htons(port); - break; - - case AF_INET6: - sa.in6.sin6_port = htons(port); - break; - - default: - logger(mesh, MESHLINK_WARNING, "Could not resolve node %s to a known address family type.\n", n->name); - sa.sa.sa_family = AF_UNKNOWN; - break; - } - - if(sa.sa.sa_family != AF_UNKNOWN) { - n->catta_address = sa; - n->last_connect_try = 0; - node_add_recent_address(mesh, n, &sa); - - if(n->connection) { - n->connection->last_ping_time = -3600; - } - - for list_each(outgoing_t, outgoing, mesh->outgoings) { - if(outgoing->node != n) { - continue; - } - - outgoing->timeout = 0; - - if(outgoing->ev.cb) { - timeout_set(&mesh->loop, &outgoing->ev, &(struct timespec) { - 0, 0 - }); - } - } - } - } - } else if(parse_request(buf, len, mesh->appname, "tcp")) { - char *fingerprint = meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self); - const char *response_values[] = {mesh->name, fingerprint}; - size_t size = prepare_response(buf, sizeof(buf), fingerprint, mesh->appname, "tcp", atoi(mesh->myport), 2, keys, response_values); - - int index = -1; - int family = AF_UNSPEC; - - for(struct cmsghdr *cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL; cmptr = CMSG_NXTHDR(&msg, cmptr)) { -#ifdef IP_PKTINFO - - if(cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) { - struct in_pktinfo *pktinfo = (struct in_pktinfo *) CMSG_DATA(cmptr); - index = pktinfo->ipi_ifindex; - family = AF_INET; - break; - } else -#endif -#ifdef IPV6_PKTINFO - if(cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == IPV6_PKTINFO) { - struct in6_pktinfo *pktinfo = (struct in6_pktinfo *) CMSG_DATA(cmptr); - index = pktinfo->ipi6_ifindex; - family = AF_INET6; - break; - } - -#endif - } - - if(index) { - // Send a multicast response back using all addresses matching the interface - for(int i = 0; i < mesh->discovery.address_count; i++) { - discovery_address_t *p = &mesh->discovery.addresses[i]; - - if(p->index == index && p->address.sa.sa_family == family) { - send_mdns_packet(mesh, p, true); - } - } - } else { - // Send a unicast response back - sendto(io->fd, buf, size, MSG_DONTWAIT | MSG_NOSIGNAL, &sa.sa, sl); - } - - free(fingerprint); - } - - free(name); - - for(int i = 0; i < 2; i++) { - free(values[i]); - } -} - -static void iface_up(meshlink_handle_t *mesh, int index) { - int *p = bsearch(&index, mesh->discovery.ifaces, mesh->discovery.iface_count, sizeof(*p), iface_compare); - - if(p) { - return; - } - - mesh->discovery.ifaces = xrealloc(mesh->discovery.ifaces, ++mesh->discovery.iface_count * sizeof(*p)); - mesh->discovery.ifaces[mesh->discovery.iface_count - 1] = index; - qsort(mesh->discovery.ifaces, mesh->discovery.iface_count, sizeof(*p), iface_compare); - - // Add multicast membership - struct ip_mreqn mreq4 = { - .imr_multiaddr = mdns_address_ipv4.in.sin_addr, - .imr_ifindex = index, - }; - - setsockopt(mesh->discovery.sockets[0].fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq4, sizeof(mreq4)); - setsockopt(mesh->discovery.sockets[0].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq4, sizeof(mreq4)); - - struct ipv6_mreq mreq6 = { - .ipv6mr_multiaddr = mdns_address_ipv6.in6.sin6_addr, - .ipv6mr_interface = index, - }; - - setsockopt(mesh->discovery.sockets[1].fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)); - setsockopt(mesh->discovery.sockets[1].fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)); - - // Send an announcement for all addresses associated with this interface - for(int i = 0; i < mesh->discovery.address_count; i++) { - if(mesh->discovery.addresses[i].index == index) { - send_mdns_packet(mesh, &mesh->discovery.addresses[i], false); - } - } - - handle_network_change(mesh, true); -} - -static void iface_down(meshlink_handle_t *mesh, int index) { - int *p = bsearch(&index, mesh->discovery.ifaces, mesh->discovery.iface_count, sizeof(*p), iface_compare); - - if(!p) { - return; - } - - // Drop multicast membership - struct ip_mreqn mreq4 = { - .imr_multiaddr = mdns_address_ipv4.in.sin_addr, - .imr_ifindex = index, - }; - setsockopt(mesh->discovery.sockets[0].fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq4, sizeof(mreq4)); - - struct ipv6_mreq mreq6 = { - .ipv6mr_multiaddr = mdns_address_ipv6.in6.sin6_addr, - .ipv6mr_interface = index, - }; - setsockopt(mesh->discovery.sockets[1].fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)); - - memmove(p, p + 1, (mesh->discovery.ifaces + --mesh->discovery.iface_count - p) * sizeof(*p)); - - handle_network_change(mesh, mesh->discovery.iface_count); -} - -static void addr_add(meshlink_handle_t *mesh, const discovery_address_t *addr) { - discovery_address_t *p = bsearch(addr, mesh->discovery.addresses, mesh->discovery.address_count, sizeof(*p), address_compare); - - if(p) { - return; - } - - bool up = bsearch(&addr->index, mesh->discovery.ifaces, mesh->discovery.iface_count, sizeof(int), iface_compare); - - mesh->discovery.addresses = xrealloc(mesh->discovery.addresses, ++mesh->discovery.address_count * sizeof(*p)); - mesh->discovery.addresses[mesh->discovery.address_count - 1] = *addr; - mesh->discovery.addresses[mesh->discovery.address_count - 1].up = up; - - if(up) { - send_mdns_packet(mesh, &mesh->discovery.addresses[mesh->discovery.address_count - 1], false); - } - - qsort(mesh->discovery.addresses, mesh->discovery.address_count, sizeof(*p), address_compare); -} - -static void addr_del(meshlink_handle_t *mesh, const discovery_address_t *addr) { - discovery_address_t *p = bsearch(addr, mesh->discovery.addresses, mesh->discovery.address_count, sizeof(*p), address_compare); - - if(!p) { - return; - } - - memmove(p, p + 1, (mesh->discovery.addresses + --mesh->discovery.address_count - p) * sizeof(*p)); -} - -void scan_ifaddrs(meshlink_handle_t *mesh) { -#ifdef HAVE_GETIFADDRS - struct ifaddrs *ifa = NULL; - - if(getifaddrs(&ifa) == -1) { - logger(mesh, MESHLINK_ERROR, "Could not get list of interface addresses: %s", strerror(errno)); - return; - } - - // Check for interfaces being removed - for(int i = 0; i < mesh->discovery.iface_count;) { - bool found = false; - - for(struct ifaddrs *ifap = ifa; ifap; ifap = ifap->ifa_next) { - if(!ifap->ifa_name) { - continue; - } - - int index = if_nametoindex(ifap->ifa_name); - - if(mesh->discovery.ifaces[i] == index) { - found = true; - break; - } - } - - if(!found) { - iface_down(mesh, mesh->discovery.ifaces[i]); - } else { - i++; - } - } - - // Check for addresses being removed - for(int i = 0; i < mesh->discovery.address_count;) { - discovery_address_t *p = &mesh->discovery.addresses[i]; - bool found = false; - - for(struct ifaddrs *ifap = ifa; ifap; ifap = ifap->ifa_next) { - if(!ifap->ifa_name || !ifap->ifa_addr) { - continue; - } - - int index = if_nametoindex(ifap->ifa_name); - - if(p->index == index && sockaddrcmp_noport(&p->address, (sockaddr_t *)ifap->ifa_addr) == 0) { - found = true; - break; - } - } - - if(!found) { - (void)addr_del; - memmove(p, p + 1, (mesh->discovery.addresses + --mesh->discovery.address_count - p) * sizeof(*p)); - } else { - i++; - } - } - - // Check for interfaces state changes and addresses going up - for(struct ifaddrs *ifap = ifa; ifap; ifap = ifap->ifa_next) { - if(!ifap->ifa_name) { - continue; - } - - int index = if_nametoindex(ifap->ifa_name); - - if(ifap->ifa_flags & IFF_UP && ifap->ifa_flags & IFF_MULTICAST && !(ifap->ifa_flags & IFF_LOOPBACK)) { - iface_up(mesh, index); - } else { - iface_down(mesh, index); - } - - if(!ifap->ifa_addr) { - continue; - } - - discovery_address_t addr = { - .index = index, - }; - - sockaddr_t *sa = (sockaddr_t *)ifap->ifa_addr; - - if(sa->sa.sa_family == AF_INET) { - memcpy(&addr.address.in, &sa->in, sizeof(sa->in)); - addr.address.in.sin_port = ntohs(5353); - } else if(sa->sa.sa_family == AF_INET6) { - memcpy(&addr.address.in6, &sa->in6, sizeof(sa->in6)); - addr.address.in6.sin6_port = ntohs(5353); - } else { - addr.address.sa.sa_family = AF_UNKNOWN; - } - - if(addr.address.sa.sa_family != AF_UNKNOWN) { - addr_add(mesh, &addr); - } - } - - freeifaddrs(ifa); -#else - (void)mesh; -#endif -} - -#if defined(__linux) -static void netlink_getlink(int fd) { - static const struct { - struct nlmsghdr nlm; - struct ifinfomsg ifi; - } msg = { - .nlm.nlmsg_len = NLMSG_LENGTH(sizeof(msg.ifi)), - .nlm.nlmsg_type = RTM_GETLINK, - .nlm.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, - .nlm.nlmsg_seq = 1, - .ifi.ifi_family = AF_UNSPEC, - }; - send(fd, &msg, msg.nlm.nlmsg_len, 0); -} - -static void netlink_getaddr(int fd) { - static const struct { - struct nlmsghdr nlm; - struct ifaddrmsg ifa; - } msg = { - .nlm.nlmsg_len = NLMSG_LENGTH(sizeof(msg.ifa)), - .nlm.nlmsg_type = RTM_GETADDR, - .nlm.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, - .nlm.nlmsg_seq = 2, - .ifa.ifa_family = AF_UNSPEC, - }; - send(fd, &msg, msg.nlm.nlmsg_len, 0); -} - -static void netlink_parse_link(meshlink_handle_t *mesh, const struct nlmsghdr *nlm) { - const struct ifinfomsg *ifi = (const struct ifinfomsg *)(nlm + 1); - - if(ifi->ifi_flags & IFF_UP && ifi->ifi_flags & IFF_MULTICAST) { - iface_up(mesh, ifi->ifi_index); - } else { - iface_down(mesh, ifi->ifi_index); - } -} - -static void netlink_parse_addr(meshlink_handle_t *mesh, const struct nlmsghdr *nlm) { - const struct ifaddrmsg *ifa = (const struct ifaddrmsg *)(nlm + 1); - const uint8_t *ptr = (const uint8_t *)(ifa + 1); - size_t len = nlm->nlmsg_len - (ptr - (const uint8_t *)nlm); - - while(len >= sizeof(struct rtattr)) { - const struct rtattr *rta = (const struct rtattr *)ptr; - - if(rta->rta_len <= 0 || rta->rta_len > len) { - break; - } - - if(rta->rta_type == IFA_ADDRESS) { - discovery_address_t addr = { - .index = ifa->ifa_index, - }; - - if(rta->rta_len == 8) { - addr.address.sa.sa_family = AF_INET; - memcpy(&addr.address.in.sin_addr, ptr + 4, 4); - addr.address.in.sin_port = ntohs(5353); - } else if(rta->rta_len == 20) { - addr.address.sa.sa_family = AF_INET6; - memcpy(&addr.address.in6.sin6_addr, ptr + 4, 16); - addr.address.in6.sin6_port = ntohs(5353); - addr.address.in6.sin6_scope_id = ifa->ifa_index; - } else { - addr.address.sa.sa_family = AF_UNKNOWN; - } - - if(addr.address.sa.sa_family != AF_UNKNOWN) { - if(nlm->nlmsg_type == RTM_NEWADDR) { - addr_add(mesh, &addr); - } else { - addr_del(mesh, &addr); - } - } - } - - unsigned short rta_len = (rta->rta_len + 3) & ~3; - ptr += rta_len; - len -= rta_len; - } -} - -static void netlink_parse(meshlink_handle_t *mesh, const void *data, size_t len) { - const uint8_t *ptr = data; - - while(len >= sizeof(struct nlmsghdr)) { - const struct nlmsghdr *nlm = (const struct nlmsghdr *)ptr; - - if(nlm->nlmsg_len > len) { - break; - } - - switch(nlm->nlmsg_type) { - case RTM_NEWLINK: - case RTM_DELLINK: - netlink_parse_link(mesh, nlm); - break; - - case RTM_NEWADDR: - case RTM_DELADDR: - netlink_parse_addr(mesh, nlm); - } - - ptr += nlm->nlmsg_len; - len -= nlm->nlmsg_len; - } -} - -static void netlink_io_handler(event_loop_t *loop, void *data, int flags) { - (void)flags; - (void)data; - meshlink_handle_t *mesh = loop->data; - - struct { - struct nlmsghdr nlm; - char data[16384]; - } msg; - - while(true) { - ssize_t result = recv(mesh->discovery.pfroute_io.fd, &msg, sizeof(msg), MSG_DONTWAIT); - - if(result <= 0) { - if(result == 0 || errno == EAGAIN || errno == EINTR) { - break; - } - - logger(mesh, MESHLINK_ERROR, "Reading from Netlink socket failed: %s\n", strerror(errno)); - io_set(loop, &mesh->discovery.pfroute_io, 0); - } - - if((size_t)result < sizeof(msg.nlm)) { - logger(mesh, MESHLINK_ERROR, "Invalid Netlink message\n"); - break; - } - - if(msg.nlm.nlmsg_type == NLMSG_DONE) { - if(msg.nlm.nlmsg_seq == 1) { - // We just got the result of GETLINK, now send GETADDR. - netlink_getaddr(mesh->discovery.pfroute_io.fd); - } - } else { - netlink_parse(mesh, &msg, result); - - if(loop->now.tv_sec > mesh->discovery.last_update + 5) { - mesh->discovery.last_update = loop->now.tv_sec; - handle_network_change(mesh, true); - } - } - } -} -#elif defined(__APPLE__) -static void reachability_change_callback(SCNetworkReachabilityRef reachability, SCNetworkReachabilityFlags flags, void *info) { - (void)reachability; - (void)flags; - - meshlink_handle_t *mesh = info; - - pthread_mutex_lock(&mesh->mutex); - - scan_ifaddrs(mesh); - - if(mesh->loop.now.tv_sec > mesh->discovery.last_update + 5) { - logger(mesh, MESHLINK_INFO, "Network change detected"); - mesh->discovery.last_update = mesh->loop.now.tv_sec; - handle_network_change(mesh, true); - } - - pthread_mutex_unlock(&mesh->mutex); -} - -static void *network_change_handler(void *arg) { - meshlink_handle_t *mesh = arg; - - mesh->discovery.runloop = CFRunLoopGetCurrent(); - - SCNetworkReachabilityRef reach_v4 = SCNetworkReachabilityCreateWithName(NULL, "93.184.216.34"); - SCNetworkReachabilityRef reach_v6 = SCNetworkReachabilityCreateWithName(NULL, "2606:2800:220:1:248:1893:25c8:1946"); - - SCNetworkReachabilityContext context; - memset(&context, 0, sizeof(context)); - context.info = mesh; - - if(reach_v4) { - SCNetworkReachabilitySetCallback(reach_v4, reachability_change_callback, &context); - SCNetworkReachabilityScheduleWithRunLoop(reach_v4, mesh->discovery.runloop, kCFRunLoopDefaultMode); - } else { - logger(mesh, MESHLINK_ERROR, "Could not create IPv4 network reachability watcher"); - } - - if(reach_v6) { - SCNetworkReachabilitySetCallback(reach_v6, reachability_change_callback, &context); - SCNetworkReachabilityScheduleWithRunLoop(reach_v6, mesh->discovery.runloop, kCFRunLoopDefaultMode); - } else { - logger(mesh, MESHLINK_ERROR, "Could not create IPv6 network reachability watcher"); - } - - CFRunLoopRun(); - - mesh->discovery.runloop = NULL; - - if(reach_v4) { - SCNetworkReachabilityUnscheduleFromRunLoop(reach_v4, mesh->discovery.runloop, kCFRunLoopDefaultMode); - CFRelease(reach_v4); - } - - if(reach_v6) { - SCNetworkReachabilityUnscheduleFromRunLoop(reach_v6, mesh->discovery.runloop, kCFRunLoopDefaultMode); - CFRelease(reach_v6); - } - - return NULL; -} -#elif defined(RTM_NEWADDR) -static void pfroute_parse_iface(meshlink_handle_t *mesh, const struct rt_msghdr *rtm) { - const struct if_msghdr *ifm = (const struct if_msghdr *)rtm; - - if(ifm->ifm_flags & IFF_UP && ifm->ifm_flags & IFF_MULTICAST && !(ifm->ifm_flags & IFF_LOOPBACK)) { - iface_up(mesh, ifm->ifm_index); - } else { - iface_down(mesh, ifm->ifm_index); - } -} - -static void pfroute_parse_addr(meshlink_handle_t *mesh, const struct rt_msghdr *rtm) { - const struct ifa_msghdr *ifam = (const struct ifa_msghdr *)rtm; - const char *p = (const char *)(ifam + 1); - - for(unsigned int i = 1; i; i <<= 1) { - if(!(ifam->ifam_addrs & i)) { - continue; - } - - const sockaddr_t *sa = (const sockaddr_t *)p; - - if(i == RTA_IFA) { - discovery_address_t addr = { - .index = ifam->ifam_index, - }; - - if(sa->sa.sa_family == AF_INET) { - addr.address.in = sa->in; - addr.address.in.sin_port = ntohs(5353); - } else if(sa->sa.sa_family == AF_INET6) { - addr.address.in6 = sa->in6; - addr.address.in6.sin6_port = ntohs(5353); - } else { - addr.address.sa.sa_family = AF_UNKNOWN; - } - - if(addr.address.sa.sa_family != AF_UNKNOWN) { - if(ifam->ifam_type == RTM_NEWADDR) { - addr_add(mesh, &addr); - } else { - addr_del(mesh, &addr); - } - } - - break; - } - - size_t len = (sa->sa.sa_len + 3) & ~3; - p += len; - } -} - -static void pfroute_io_handler(event_loop_t *loop, void *data, int flags) { - (void)flags; - (void)data; - meshlink_handle_t *mesh = loop->data; - - struct { - struct rt_msghdr rtm; - char data[2048]; - } msg; - - while(true) { - msg.rtm.rtm_version = 0; - ssize_t result = recv(mesh->discovery.pfroute_io.fd, &msg, sizeof(msg), MSG_DONTWAIT); - - if(result <= 0) { - if(result == 0 || errno == EAGAIN || errno == EINTR) { - break; - } - - logger(mesh, MESHLINK_ERROR, "Reading from PFROUTE socket failed: %s\n", strerror(errno)); - io_set(loop, &mesh->discovery.pfroute_io, 0); - } - - if(msg.rtm.rtm_version != RTM_VERSION) { - logger(mesh, MESHLINK_ERROR, "Invalid PFROUTE message version\n"); - break; - } - - switch(msg.rtm.rtm_type) { - case RTM_IFINFO: - pfroute_parse_iface(mesh, &msg.rtm); - break; - - case RTM_NEWADDR: - case RTM_DELADDR: - pfroute_parse_addr(mesh, &msg.rtm); - break; - - default: - break; - } - } -} -#endif - -bool discovery_start(meshlink_handle_t *mesh) { - logger(mesh, MESHLINK_DEBUG, "discovery_start called\n"); - - assert(mesh); - - // Set up multicast sockets for mDNS - static const int one = 1; - static const int ttl = 255; - static const uint8_t one8 = 1; - static const uint8_t ttl8 = 255; - - int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - - if(fd == -1) { - logger(mesh, MESHLINK_ERROR, "Error creating IPv4 socket: %s", strerror(errno)); - } else { - - sockaddr_t sa4 = { - .in.sin_family = AF_INET, - .in.sin_port = ntohs(5353), - }; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); -#ifdef SO_REUSEPORT - setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); -#endif -#ifdef IP_PKTINFO - setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); -#endif - setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one8, sizeof(one8)); - setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl8, sizeof(ttl8)); - - if(bind(fd, &sa4.sa, SALEN(sa4.sa)) == -1) { - logger(mesh, MESHLINK_ERROR, "Error binding to IPv4 multicast socket: %s", strerror(errno)); - } else { - io_add(&mesh->loop, &mesh->discovery.sockets[0], mdns_io_handler, &mesh->discovery.sockets[0], fd, IO_READ); - } - } - - fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - - if(fd == -1) { - logger(mesh, MESHLINK_ERROR, "Error creating IPv6 socket: %s", strerror(errno)); - } else { - sockaddr_t sa6 = { - .in6.sin6_family = AF_INET6, - .in6.sin6_port = ntohs(5353), - }; - - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); -#ifdef SO_REUSEPORT - setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); -#endif -#ifdef IPV6_RECVPKTINFO - setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); -#endif - setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); - setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one)); - setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); - setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); - - if(bind(fd, &sa6.sa, SALEN(sa6.sa)) == -1) { - logger(mesh, MESHLINK_ERROR, "Error binding to IPv6 multicast socket: %s", strerror(errno)); - } else { - io_add(&mesh->loop, &mesh->discovery.sockets[1], mdns_io_handler, &mesh->discovery.sockets[1], fd, IO_READ); - } - } - -#if defined(__linux) - int sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - - if(sock != -1) { - struct sockaddr_nl sa; - memset(&sa, 0, sizeof(sa)); - sa.nl_family = AF_NETLINK; - sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; - - if(bind(sock, (struct sockaddr *)&sa, sizeof(sa)) != -1) { - io_add(&mesh->loop, &mesh->discovery.pfroute_io, netlink_io_handler, NULL, sock, IO_READ); - netlink_getlink(sock); - } else { - logger(mesh, MESHLINK_WARNING, "Could not bind AF_NETLINK socket: %s", strerror(errno)); - scan_ifaddrs(mesh); - } - } else { - logger(mesh, MESHLINK_WARNING, "Could not open AF_NETLINK socket: %s", strerror(errno)); - scan_ifaddrs(mesh); - } - -#elif defined(__APPLE__) - pthread_create(&mesh->discovery.thread, NULL, network_change_handler, mesh); - // TODO: Do we need to wait for the thread to start succesfully? - scan_ifaddrs(mesh); -#elif defined(RTM_NEWADDR) - int sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); - - if(sock != -1) { - io_add(&mesh->loop, &mesh->discovery.pfroute_io, pfroute_io_handler, NULL, sock, IO_READ); - } else { - logger(mesh, MESHLINK_WARNING, "Could not open PF_ROUTE socket: %s", strerror(errno)); - } - - scan_ifaddrs(mesh); -#endif - - return true; -} - -void discovery_stop(meshlink_handle_t *mesh) { - logger(mesh, MESHLINK_DEBUG, "discovery_stop called\n"); - - assert(mesh); - - free(mesh->discovery.ifaces); - free(mesh->discovery.addresses); - mesh->discovery.ifaces = NULL; - mesh->discovery.addresses = NULL; - mesh->discovery.iface_count = 0; - mesh->discovery.address_count = 0; - -#if defined(__APPLE__) - - if(mesh->discovery.runloop) { - CFRunLoopStop(mesh->discovery.runloop); - pthread_join(mesh->discovery.thread, NULL); - } - -#endif - - if(mesh->discovery.pfroute_io.cb) { - close(mesh->discovery.pfroute_io.fd); - io_del(&mesh->loop, &mesh->discovery.pfroute_io); - } - - for(int i = 0; i < 2; i++) { - if(mesh->discovery.sockets[i].cb) { - close(mesh->discovery.sockets[i].fd); - io_del(&mesh->loop, &mesh->discovery.sockets[i]); - } - } -} - -void discovery_refresh(meshlink_handle_t *mesh) { - for(int i = 0; i < mesh->discovery.address_count; i++) { - if(mesh->discovery.addresses[i].up) { - send_mdns_packet(mesh, &mesh->discovery.addresses[i], false); - } - } -} diff --git a/src/discovery.h b/src/discovery.h deleted file mode 100644 index 03c4312..0000000 --- a/src/discovery.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef MESHLINK_DISCOVERY_H -#define MESHLINK_DISCOVERY_H - -/* - discovery.h -- header for discovery.c - Copyright (C) 2014-2021 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include - -bool discovery_start(meshlink_handle_t *mesh); -void discovery_stop(meshlink_handle_t *mesh); -void discovery_refresh(meshlink_handle_t *mesh); -void scan_ifaddrs(meshlink_handle_t *mesh); - -#endif diff --git a/src/edge.c b/src/edge.c deleted file mode 100644 index afe9cfe..0000000 --- a/src/edge.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - edge.c -- edge tree management - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "splay_tree.h" -#include "edge.h" -#include "logger.h" -#include "meshlink_internal.h" -#include "netutl.h" -#include "node.h" -#include "utils.h" -#include "xalloc.h" - -static int edge_compare(const edge_t *a, const edge_t *b) { - return strcmp(a->to->name, b->to->name); -} - -static int edge_weight_compare(const edge_t *a, const edge_t *b) { - int result; - - result = a->weight - b->weight; - - if(result) { - return result; - } - - result = strcmp(a->from->name, b->from->name); - - if(result) { - return result; - } - - return strcmp(a->to->name, b->to->name); -} - -void init_edges(meshlink_handle_t *mesh) { - mesh->edges = splay_alloc_tree((splay_compare_t) edge_weight_compare, NULL); -} - -splay_tree_t *new_edge_tree(void) { - return splay_alloc_tree((splay_compare_t) edge_compare, (splay_action_t) free_edge); -} - -void free_edge_tree(splay_tree_t *edge_tree) { - splay_delete_tree(edge_tree); -} - -void exit_edges(meshlink_handle_t *mesh) { - if(mesh->edges) { - splay_delete_tree(mesh->edges); - } - - mesh->edges = NULL; -} - -/* Creation and deletion of connection elements */ - -edge_t *new_edge(void) { - return xzalloc(sizeof(edge_t)); -} - -void free_edge(edge_t *e) { - sockaddrfree(&e->address); - - free(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 = lookup_edge(e->to, e->from); - - if(e->reverse) { - e->reverse->reverse = e; - } -} - -void edge_del(meshlink_handle_t *mesh, edge_t *e) { - if(e->reverse) { - e->reverse->reverse = NULL; - } - - splay_delete(mesh->edges, e); - splay_delete(e->from->edge_tree, e); -} - -edge_t *lookup_edge(node_t *from, node_t *to) { - assert(from); - assert(to); - - edge_t v; - - v.from = from; - v.to = to; - - return splay_search(from->edge_tree, &v); -} diff --git a/src/edge.h b/src/edge.h deleted file mode 100644 index d5ec117..0000000 --- a/src/edge.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef MESHLINK_EDGE_H -#define MESHLINK_EDGE_H - -/* - edge.h -- header for edge.c - Copyright (C) 2014, 2017 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "splay_tree.h" -#include "connection.h" -#include "net.h" -#include "node.h" - -typedef struct edge_t { - struct node_t *from; - struct node_t *to; - sockaddr_t address; - - struct connection_t *connection; /* connection associated with this edge, if available */ - struct edge_t *reverse; /* edge in the opposite direction, if available */ - - int weight; /* weight of this edge */ - uint32_t session_id; /* the session_id of the from node */ -} edge_t; - -void init_edges(struct meshlink_handle *mesh); -void exit_edges(struct meshlink_handle *mesh); -edge_t *new_edge(void) __attribute__((__malloc__)); -void free_edge(edge_t *); -struct splay_tree_t *new_edge_tree(void) __attribute__((__malloc__)); -void free_edge_tree(struct splay_tree_t *); -void edge_add(struct meshlink_handle *mesh, edge_t *); -void edge_del(struct meshlink_handle *mesh, edge_t *); -edge_t *lookup_edge(struct node_t *, struct node_t *) __attribute__((__warn_unused_result__)); - -#endif diff --git a/src/graph.c b/src/graph.c deleted file mode 100644 index 9a2bfb1..0000000 --- a/src/graph.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - graph.c -- graph algorithms - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -/* We need to generate two trees from the graph: - - 1. A minimum spanning tree for broadcasts, - 2. A single-source shortest path tree for unicasts. - - Actually, the first one alone would suffice but would make unicast packets - take longer routes than necessary. - - For the MST algorithm we can choose from Prim's or Kruskal's. I personally - favour Kruskal's, because we make an extra AVL tree of edges sorted on - weights (metric). That tree only has to be updated when an edge is added or - removed, and during the MST algorithm we just have go linearly through that - tree, adding safe edges until #edges = #nodes - 1. The implementation here - however is not so fast, because I tried to avoid having to make a forest and - merge trees. - - For the SSSP algorithm Dijkstra's seems to be a nice choice. Currently a - simple breadth-first search is presented here. - - The SSSP algorithm will also be used to determine whether nodes are - reachable from the source. It will also set the correct destination address - and port of a node if possible. -*/ - -#include "system.h" - -#include "connection.h" -#include "edge.h" -#include "graph.h" -#include "list.h" -#include "logger.h" -#include "meshlink_internal.h" -#include "netutl.h" -#include "node.h" -#include "protocol.h" -#include "utils.h" -#include "xalloc.h" -#include "graph.h" - -/* Implementation of a simple breadth-first search algorithm. - Running time: O(E) -*/ - -static void sssp_bfs(meshlink_handle_t *mesh) { - list_t *todo_list = list_alloc(NULL); - - /* Clear visited status on nodes */ - - for splay_each(node_t, n, mesh->nodes) { - n->status.visited = false; - n->distance = -1; - } - - /* Begin with mesh->self */ - - mesh->self->status.visited = mesh->threadstarted; - mesh->self->nexthop = mesh->self; - mesh->self->prevedge = NULL; - mesh->self->distance = 0; - list_insert_head(todo_list, mesh->self); - - /* Loop while todo_list is filled */ - - for list_each(node_t, n, todo_list) { /* "n" is the node from which we start */ - logger(mesh, MESHLINK_DEBUG, " Examining edges from %s", n->name); - - if(n->distance < 0) { - abort(); - } - - for splay_each(edge_t, e, n->edge_tree) { /* "e" is the edge connected to "from" */ - if(!e->reverse) { - continue; - } - - /* Situation: - - / - / - ----->(n)---e-->(e->to) - \ - \ - - Where e is an edge, (n) and (e->to) are nodes. - n->address is set to the e->address of the edge left of n to n. - We are currently examining the edge e right of n from n: - - - If edge e provides for better reachability of e->to, update - e->to and (re)add it to the todo_list to (re)examine the reachability - of nodes behind it. - */ - - if(e->to->status.visited - && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) { - continue; - } - - e->to->status.visited = true; - e->to->nexthop = (n->nexthop == mesh->self) ? e->to : n->nexthop; - e->to->prevedge = e; - 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(mesh, e->to, &e->address); - } - - list_insert_tail(todo_list, e->to); - } - - list_next = list_node->next; /* Because the list_insert_tail() above could have added something extra for us! */ - list_delete_node(todo_list, list_node); - } - - list_free(todo_list); -} - -static void check_reachability(meshlink_handle_t *mesh) { - /* Check reachability status. */ - - int reachable = -1; /* Don't count ourself */ - - for splay_each(node_t, n, mesh->nodes) { - if(n->status.visited) { - reachable++; - } - - /* Check for nodes that have changed session_id */ - if(n->status.visited && n->prevedge && n->prevedge->reverse->session_id != n->session_id) { - logger(mesh, MESHLINK_DEBUG, "Node %s has a new session ID", n->name); - - n->session_id = n->prevedge->reverse->session_id; - - if(n->utcp) { - utcp_reset_all_connections(n->utcp); - } - - n->status.validkey = false; - sptps_stop(&n->sptps); - n->status.waitingforkey = false; - n->last_req_key = -3600; - - n->status.udp_confirmed = false; - n->maxmtu = MTU; - n->minmtu = 0; - n->mtuprobes = 0; - - timeout_del(&mesh->loop, &n->mtutimeout); - } - - if(n->status.visited != n->status.reachable) { - n->status.reachable = !n->status.reachable; - n->status.dirty = true; - - if(!n->status.blacklisted) { - if(n->status.reachable) { - logger(mesh, MESHLINK_DEBUG, "Node %s became reachable", n->name); - bool first_time_reachable = !n->last_reachable; - n->last_reachable = time(NULL); - - if(first_time_reachable) { - if(!node_write_config(mesh, n, false)) { - logger(mesh, MESHLINK_WARNING, "Could not write host config file for node %s!\n", n->name); - - } - } - } else { - logger(mesh, MESHLINK_DEBUG, "Node %s became unreachable", n->name); - n->last_unreachable = time(NULL); - } - } - - n->status.udp_confirmed = false; - n->maxmtu = MTU; - n->minmtu = 0; - n->mtuprobes = 0; - - timeout_del(&mesh->loop, &n->mtutimeout); - - if(!n->status.blacklisted) { - update_node_status(mesh, n); - } - - if(!n->status.reachable) { - update_node_udp(mesh, n, NULL); - n->status.broadcast = false; - } - - if(n->utcp) { - utcp_offline(n->utcp, !n->status.reachable); - } - } - } - - if(mesh->reachable != reachable) { - if(!reachable) { - mesh->last_unreachable = mesh->loop.now.tv_sec; - - if(mesh->threadstarted && mesh->periodictimer.cb) { - timeout_set(&mesh->loop, &mesh->periodictimer, &(struct timespec) { - 0, prng(mesh, TIMER_FUDGE) - }); - } - } - - mesh->reachable = reachable; - } -} - -void graph(meshlink_handle_t *mesh) { - sssp_bfs(mesh); - check_reachability(mesh); -} diff --git a/src/graph.h b/src/graph.h deleted file mode 100644 index 1775732..0000000 --- a/src/graph.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef MESHLINK_GRAPH_H -#define MESHLINK_GRAPH_H - -/* - graph.h -- header for graph.c - Copyright (C) 2014, 2017 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -void graph(struct meshlink_handle *mesh); - -#endif diff --git a/src/mdns.c b/src/mdns.c deleted file mode 100644 index e92a833..0000000 --- a/src/mdns.c +++ /dev/null @@ -1,441 +0,0 @@ -// SPDX-FileCopyrightText: 2020 Guus Sliepen -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "system.h" - -#include - -#include "mdns.h" -#include "xalloc.h" - -// Creating a buffer - -typedef struct { - uint8_t *ptr; - ptrdiff_t len; -} buf_t; - -static void buf_add(buf_t *buf, const void *data, uint32_t len) { - if(buf->len >= len) { - memcpy(buf->ptr, data, len); - buf->ptr += len; - buf->len -= len; - } else { - buf->len = -1; - } -} - -static void buf_add_uint8(buf_t *buf, uint8_t val) { - if(buf->len >= 1) { - buf->ptr[0] = val; - buf->ptr++; - buf->len--; - } else { - buf->len = -1; - } -} - -static void buf_add_uint16(buf_t *buf, uint16_t val) { - uint16_t nval = htons(val); - buf_add(buf, &nval, sizeof(nval)); -} - -static void buf_add_uint32(buf_t *buf, uint32_t val) { - uint32_t nval = htonl(val); - buf_add(buf, &nval, sizeof(nval)); -} - -static void buf_add_label(buf_t *buf, const char *str) { - size_t len = strlen(str); - - if(len < 256) { - buf_add_uint8(buf, len); - buf_add(buf, str, len); - } else { - buf->len = -1; - } -} - -static void buf_add_ulabel(buf_t *buf, const char *str) { - size_t len = strlen(str); - - if(len + 1 < 256) { - buf_add_uint8(buf, len + 1); - buf_add_uint8(buf, '_'); - buf_add(buf, str, len); - } else { - buf->len = -1; - } -} - -static void buf_add_kvp(buf_t *buf, const char *key, const char *val) { - size_t key_len = strlen(key); - size_t val_len = strlen(val); - - if(key_len + val_len + 1 < 256) { - buf_add_uint8(buf, key_len + val_len + 1); - buf_add(buf, key, key_len); - buf_add_uint8(buf, '='); - buf_add(buf, val, val_len); - } else { - buf->len = -1; - } -} - -static uint8_t *buf_len_start(buf_t *buf) { - if(buf->len < 2) { - buf->len = -1; - return NULL; - } else { - uint8_t *ptr = buf->ptr; - buf->ptr += 2; - buf->len -= 2; - return ptr; - } -} - -static void buf_len_end(buf_t *buf, uint8_t *ptr) { - if(buf->len < 0) { - return; - } - - uint16_t len = htons(buf->ptr - ptr - 2); - memcpy(ptr, &len, sizeof(len)); -} - -// Functions reading a buffer - -typedef struct { - const uint8_t *ptr; - ptrdiff_t len; -} cbuf_t; - -static void buf_check(cbuf_t *buf, const void *data, uint32_t len) { - if(buf->len >= len && !memcmp(buf->ptr, data, len)) { - buf->ptr += len; - buf->len -= len; - } else { - buf->len = -1; - } -} - -static void buf_check_uint8(cbuf_t *buf, uint8_t val) { - if(buf->len >= 1 && buf->ptr[0] == val) { - buf->ptr++; - buf->len--; - } else { - buf->len = -1; - } -} - -static void buf_check_uint16(cbuf_t *buf, uint16_t val) { - uint16_t nval = htons(val); - buf_check(buf, &nval, sizeof(nval)); -} - -static uint16_t buf_get_uint16(cbuf_t *buf) { - uint16_t nval; - - if(buf->len >= 2) { - memcpy(&nval, buf->ptr, 2); - buf->ptr += 2; - buf->len -= 2; - return ntohs(nval); - } else { - buf->len = -1; - return 0; - } -} - -static void buf_check_uint32(cbuf_t *buf, uint32_t val) { - uint32_t nval = htonl(val); - buf_check(buf, &nval, sizeof(nval)); -} - -static void buf_check_label(cbuf_t *buf, const char *str) { - size_t len = strlen(str); - - if(len < 256) { - buf_check_uint8(buf, len); - buf_check(buf, str, len); - } else { - buf->len = -1; - } -} - -static char *buf_get_label(cbuf_t *buf) { - if(buf->len < 1) { - buf->len = -1; - return NULL; - } - - uint8_t len = buf->ptr[0]; - buf->ptr++; - buf->len--; - - if(buf->len < len) { - buf->len = -1; - return NULL; - } - - char *label = xmalloc(len + 1); - memcpy(label, buf->ptr, len); - label[len] = 0; - buf->ptr += len; - buf->len -= len; - return label; -} - -static void buf_check_ulabel(cbuf_t *buf, const char *str) { - size_t len = strlen(str); - - if(len + 1 < 256) { - buf_check_uint8(buf, len + 1); - buf_check_uint8(buf, '_'); - buf_check(buf, str, len); - } else { - buf->len = -1; - } -} - -static void buf_get_kvp(cbuf_t *buf, const char *key, char **val) { - char *kvp = buf_get_label(buf); - - if(buf->len == -1) { - return; - } - - char *split = strchr(kvp, '='); - - if(!split) { - buf->len = -1; - return; - } - - *split++ = 0; - - if(strcmp(kvp, key)) { - buf->len = -1; - return; - } - - memmove(kvp, split, strlen(split) + 1); - *val = kvp; -} - -static const uint8_t *buf_check_len_start(cbuf_t *buf) { - if(buf->len < 2) { - buf->len = -1; - return NULL; - } else { - const uint8_t *ptr = buf->ptr; - buf->ptr += 2; - buf->len -= 2; - return ptr; - } -} - -static void buf_check_len_end(cbuf_t *buf, const uint8_t *ptr) { - if(buf->len < 0) { - return; - } - - uint16_t len = htons(buf->ptr - ptr - 2); - - if(memcmp(ptr, &len, sizeof(len))) { - buf->len = -1; - } -} - -size_t prepare_request(void *vdata, size_t size, const char *protocol, const char *transport) { - uint8_t *data = vdata; - buf_t buf = {data, size}; - - // Header - buf_add_uint16(&buf, 0); // TX ID - buf_add_uint16(&buf, 0); // flags - buf_add_uint16(&buf, 1); // 1 question - buf_add_uint16(&buf, 0); // 0 answer RR - buf_add_uint16(&buf, 0); // 0 authority RRs - buf_add_uint16(&buf, 0); // 0 additional RR - - // Question section: _protocol._transport.local PTR IN - buf_add_ulabel(&buf, protocol); - buf_add_ulabel(&buf, transport); - buf_add_label(&buf, "local"); - buf_add_uint8(&buf, 0); - buf_add_uint16(&buf, 0xc); // PTR - buf_add_uint16(&buf, 0x1); // IN - - // Done. - if(buf.len < 0) { - return 0; - } else { - return buf.ptr - data; - } -} - -bool parse_request(const void *vdata, size_t size, const char *protocol, const char *transport) { - const uint8_t *data = vdata; - cbuf_t buf = {data, size}; - - // Header - buf_get_uint16(&buf); // TX ID - buf_check_uint16(&buf, 0); // flags - buf_check_uint16(&buf, 1); // 1 question - buf_get_uint16(&buf); // ? answer RR - buf_get_uint16(&buf); // ? authority RRs - buf_get_uint16(&buf); // ? additional RR - - if(buf.len == -1) { - return false; - } - - // Question section: _protocol._transport.local PTR IN - buf_check_ulabel(&buf, protocol); - buf_check_ulabel(&buf, transport); - buf_check_label(&buf, "local"); - buf_check_uint8(&buf, 0); - buf_check_uint16(&buf, 0xc); // PTR - buf_check_uint16(&buf, 0x1); // IN - - if(buf.len == -1) { - return false; - } - - // Done. - return buf.len != -1; -} - -size_t prepare_response(void *vdata, size_t size, const char *name, const char *protocol, const char *transport, uint16_t port, int nkeys, const char **keys, const char **values) { - uint8_t *data = vdata; - buf_t buf = {data, size}; - - // Header - buf_add_uint16(&buf, 0); // TX ID - buf_add_uint16(&buf, 0x8400); // flags - buf_add_uint16(&buf, 0); // 1 question - buf_add_uint16(&buf, 3); // 1 answer RR - buf_add_uint16(&buf, 0); // 0 authority RRs - buf_add_uint16(&buf, 0); // 1 additional RR - - // Add the TXT record: _protocol._transport local TXT IN 3600 name._protocol._transport key=value... - uint16_t full_name = buf.ptr - data; // remember start of full name - buf_add_label(&buf, name); - uint16_t protocol_offset = buf.ptr - data; // remember start of _protocol - buf_add_ulabel(&buf, protocol); - buf_add_ulabel(&buf, transport); - uint16_t local_offset = buf.ptr - data; // remember start of local - buf_add_label(&buf, "local"); - buf_add_uint8(&buf, 0); - buf_add_uint16(&buf, 0x10); // TXT - buf_add_uint16(&buf, 0x1); // IN - buf_add_uint32(&buf, 3600); // TTL - - uint8_t *len_ptr = buf_len_start(&buf); - - for(int i = 0; i < nkeys; i++) { - buf_add_kvp(&buf, keys[i], values[i]); - } - - buf_len_end(&buf, len_ptr); - - // Add the PTR record: _protocol._transport.local PTR IN 3600 name._protocol._transport.local - buf_add_uint16(&buf, 0xc000 | protocol_offset); - buf_add_uint16(&buf, 0xc); // PTR - buf_add_uint16(&buf, 0x8001); // IN (flush) - buf_add_uint32(&buf, 3600); // TTL - len_ptr = buf_len_start(&buf); - buf_add_uint16(&buf, 0xc000 | full_name); - buf_len_end(&buf, len_ptr); - - // Add the SRV record: name._protocol._transport.local SRV IN 120 0 0 port name.local - buf_add_uint16(&buf, 0xc000 | full_name); - buf_add_uint16(&buf, 0x21); // SRV - buf_add_uint16(&buf, 0x8001); // IN (flush) - buf_add_uint32(&buf, 120); // TTL - len_ptr = buf_len_start(&buf); - buf_add_uint16(&buf, 0); // priority - buf_add_uint16(&buf, 0); // weight - buf_add_uint16(&buf, port); // port - buf_add_label(&buf, name); - buf_add_uint16(&buf, 0xc000 | local_offset); - buf_len_end(&buf, len_ptr); - - // Done. - if(buf.len < 0) { - return 0; - } else { - return buf.ptr - data; - } -} - -bool parse_response(const void *vdata, size_t size, char **name, const char *protocol, const char *transport, uint16_t *port, int nkeys, const char **keys, char **values) { - const uint8_t *data = vdata; - cbuf_t buf = {data, size}; - - // Header - buf_check_uint16(&buf, 0); // TX ID - buf_check_uint16(&buf, 0x8400); // flags - buf_check_uint16(&buf, 0); // 0 question - buf_check_uint16(&buf, 3); // 1 answer RR - buf_check_uint16(&buf, 0); // 0 authority RRs - buf_check_uint16(&buf, 0); // 0 checkitional RR - - if(buf.len == -1) { - return false; - } - - // Check the TXT record: _protocol._transport local TXT IN 3600 name._protocol._transport key=value... - uint16_t full_name = buf.ptr - data; // remember start of full name - *name = buf_get_label(&buf); - uint16_t protocol_offset = buf.ptr - data; // remember start of _protocol - buf_check_ulabel(&buf, protocol); - buf_check_ulabel(&buf, transport); - uint16_t local_offset = buf.ptr - data; // remember start of local - buf_check_label(&buf, "local"); - buf_check_uint8(&buf, 0); - buf_check_uint16(&buf, 0x10); // TXT - buf_check_uint16(&buf, 0x1); // IN - buf_check_uint32(&buf, 3600); // TTL - const uint8_t *len_ptr = buf_check_len_start(&buf); - - for(int i = 0; i < nkeys; i++) { - buf_get_kvp(&buf, keys[i], &values[i]); - } - - buf_check_len_end(&buf, len_ptr); - - if(buf.len == -1) { - return false; - } - - // Check the PTR record: _protocol._transport.local PTR IN 3600 name._protocol._transport.local - buf_check_uint16(&buf, 0xc000 | protocol_offset); - buf_check_uint16(&buf, 0xc); // PTR - buf_check_uint16(&buf, 0x8001); // IN (flush) - buf_check_uint32(&buf, 3600); // TTL - len_ptr = buf_check_len_start(&buf); - buf_check_uint16(&buf, 0xc000 | full_name); - buf_check_len_end(&buf, len_ptr); - - if(buf.len == -1) { - return false; - } - - // Check the SRV record: name._protocol._transport.local SRV IN 120 0 0 port name.local - buf_check_uint16(&buf, 0xc000 | full_name); - buf_check_uint16(&buf, 0x21); // SRV - buf_check_uint16(&buf, 0x8001); // IN (flush) - buf_check_uint32(&buf, 120); // TTL - len_ptr = buf_check_len_start(&buf); - buf_check_uint16(&buf, 0); // priority - buf_check_uint16(&buf, 0); // weight - *port = buf_get_uint16(&buf); // port - buf_check_label(&buf, *name); - buf_check_uint16(&buf, 0xc000 | local_offset); - buf_check_len_end(&buf, len_ptr); - - // Done. - return buf.len == 0; -} diff --git a/src/mdns.h b/src/mdns.h deleted file mode 100644 index 6029158..0000000 --- a/src/mdns.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -// SPDX-FileCopyrightText: 2020 Guus Sliepen -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include - -size_t prepare_packet(void *buf, size_t size, const char *name, const char *protocol, const char *transport, uint16_t port, int nkeys, const char **keys, const char **values, bool response); -size_t prepare_request(void *buf, size_t size, const char *protocol, const char *transport); -size_t prepare_response(void *buf, size_t size, const char *name, const char *protocol, const char *transport, uint16_t port, int nkeys, const char **keys, const char **values); -bool parse_response(const void *buf, size_t size, char **name, const char *protocol, const char *transport, uint16_t *port, int nkeys, const char **keys, char **values); -bool parse_request(const void *buf, size_t size, const char *protocol, const char *transport); - diff --git a/src/meshlink-tiny++.h b/src/meshlink-tiny++.h index b9e7bb7..fbe0b29 100644 --- a/src/meshlink-tiny++.h +++ b/src/meshlink-tiny++.h @@ -1017,16 +1017,6 @@ public: return meshlink_channel_get_mss(handle, channel); }; - /// Enable or disable zeroconf discovery of local peers - /** This controls whether zeroconf discovery using the Catta library will be - * enabled to search for peers on the local network. By default, it is enabled. - * - * @param enable Set to true to enable discovery, false to disable. - */ - void enable_discovery(bool enable = true) { - meshlink_enable_discovery(handle, enable); - } - /// Inform MeshLink that the local network configuration might have changed /** This is intended to be used when there is no way for MeshLink to get notifications of local network changes. * It forces MeshLink to scan all network interfaces for changes in up/down status and new/removed addresses, @@ -1080,17 +1070,6 @@ public: meshlink_set_inviter_commits_first(handle, inviter_commits_first); } - /// Set the URL used to discover the host's external address - /** For generating invitation URLs, MeshLink can look up the externally visible address of the local node. - * It does so by querying an external service. By default, this is http://meshlink.io/host.cgi. - * Only URLs starting with http:// are supported. - * - * @param url The URL to use for external address queries, or NULL to revert back to the default URL. - */ - void set_external_address_discovery_url(const char *url) { - meshlink_set_external_address_discovery_url(handle, url); - } - private: // non-copyable: mesh(const mesh &) /* TODO: C++11: = delete */; diff --git a/src/meshlink-tiny.h b/src/meshlink-tiny.h index 8dbe725..0ee3f1a 100644 --- a/src/meshlink-tiny.h +++ b/src/meshlink-tiny.h @@ -1544,16 +1544,6 @@ void meshlink_set_node_channel_timeout(struct meshlink_handle *mesh, struct mesh */ void meshlink_hint_address(struct meshlink_handle *mesh, struct meshlink_node *node, const struct sockaddr *addr); -/// Enable or disable zeroconf discovery of local peers -/** This controls whether zeroconf discovery using the Catta library will be - * enabled to search for peers on the local network. By default, it is enabled. - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - * @param enable Set to true to enable discovery, false to disable. - */ -void meshlink_enable_discovery(struct meshlink_handle *mesh, bool enable); - /// Inform MeshLink that the local network configuration might have changed /** This is intended to be used when there is no way for MeshLink to get notifications of local network changes. * It forces MeshLink to scan all network interfaces for changes in up/down status and new/removed addresses, @@ -1630,17 +1620,6 @@ void meshlink_reset_timers(struct meshlink_handle *mesh); */ void meshlink_set_inviter_commits_first(struct meshlink_handle *mesh, bool inviter_commits_first); -/// Set the URL used to discover the host's external address -/** For generating invitation URLs, MeshLink can look up the externally visible address of the local node. - * It does so by querying an external service. By default, this is http://meshlink.io/host.cgi. - * Only URLs starting with http:// are supported. - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - * @param url The URL to use for external address queries, or NULL to revert back to the default URL. - */ -void meshlink_set_external_address_discovery_url(struct meshlink_handle *mesh, const char *url); - /// Set the scheduling granularity of the application /** This should be set to the effective scheduling granularity for the application. * This depends on the scheduling granularity of the operating system, the application's diff --git a/src/meshlink.c b/src/meshlink.c index 0d607fe..abec7f4 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -37,9 +37,7 @@ #include "utils.h" #include "xalloc.h" #include "ed25519/sha512.h" -#include "discovery.h" #include "devtools.h" -#include "graph.h" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 @@ -464,18 +462,7 @@ static bool try_bind(meshlink_handle_t *mesh, int port) { } } - /* If TCP worked, then we require that UDP works as well. */ - - int udp_fd = setup_udp_listen_socket(mesh, aip); - - if(udp_fd == -1) { - closesocket(tcp_fd); - success = false; - break; - } - closesocket(tcp_fd); - closesocket(udp_fd); success = true; } @@ -656,10 +643,6 @@ static bool finalize_join(join_state_t *state, const void *buf, uint16_t len) { } } - /* Clear the reachability times, since we ourself have never seen these nodes yet */ - n->last_reachable = 0; - n->last_unreachable = 0; - if(!node_write_config(mesh, n, true)) { free_node(n); return false; @@ -1369,7 +1352,6 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { mesh->appname = xstrdup(params->appname); mesh->devclass = params->devclass; - mesh->discovery.enabled = true; mesh->netns = params->netns; mesh->submeshes = NULL; mesh->log_cb = global_log_cb; @@ -1545,10 +1527,6 @@ static void *meshlink_main_loop(void *arg) { #endif // HAVE_SETNS } - if(mesh->discovery.enabled) { - discovery_start(mesh); - } - if(pthread_mutex_lock(&mesh->mutex) != 0) { abort(); } @@ -1560,11 +1538,6 @@ static void *meshlink_main_loop(void *arg) { pthread_mutex_unlock(&mesh->mutex); - // Stop discovery - if(mesh->discovery.enabled) { - discovery_stop(mesh); - } - return NULL; } @@ -1636,9 +1609,6 @@ bool meshlink_start(meshlink_handle_t *mesh) { pthread_cond_wait(&mesh->cond, &mesh->mutex); mesh->threadstarted = true; - // Ensure we are considered reachable - graph(mesh); - pthread_mutex_unlock(&mesh->mutex); return true; } @@ -1658,20 +1628,7 @@ void meshlink_stop(meshlink_handle_t *mesh) { // Shut down the main thread event_loop_stop(&mesh->loop); - // Send ourselves a UDP packet to kick the event loop - for(int i = 0; i < mesh->listen_sockets; i++) { - sockaddr_t sa; - socklen_t salen = sizeof(sa); - - if(getsockname(mesh->listen_socket[i].udp.fd, &sa.sa, &salen) == -1) { - logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "getsockname", sockstrerror(sockerrno)); - continue; - } - - if(sendto(mesh->listen_socket[i].udp.fd, "", 1, MSG_NOSIGNAL, &sa.sa, salen) == -1) { - logger(mesh, MESHLINK_ERROR, "Could not send a UDP packet to ourself: %s", sockstrerror(sockerrno)); - } - } + // TODO: send something to a local socket to kick the event loop if(mesh->threadstarted) { // Wait for the main thread to finish @@ -1701,11 +1658,6 @@ void meshlink_stop(meshlink_handle_t *mesh) { exit_adns(mesh); exit_outgoings(mesh); - // Ensure we are considered unreachable - if(mesh->nodes) { - graph(mesh); - } - // Try to write out any changed node config files, ignore errors at this point. if(mesh->nodes) { for splay_each(node_t, n, mesh->nodes) { @@ -2289,26 +2241,6 @@ struct time_range { time_t end; }; -static bool search_node_by_last_reachable(const node_t *node, const void *condition) { - const struct time_range *range = condition; - time_t start = node->last_reachable; - time_t end = node->last_unreachable; - - if(end < start) { - end = time(NULL); - - if(end < start) { - start = end; - } - } - - if(range->end >= range->start) { - return start <= range->end && end >= range->start; - } else { - return start > range->start || end < range->end; - } -} - meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, dev_class_t devclass, meshlink_node_t **nodes, size_t *nmemb) { if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT || !nmemb) { meshlink_errno = MESHLINK_EINVAL; @@ -2327,17 +2259,6 @@ meshlink_node_t **meshlink_get_all_nodes_by_submesh(meshlink_handle_t *mesh, mes return meshlink_get_all_nodes_by_condition(mesh, submesh, nodes, nmemb, search_node_by_submesh); } -meshlink_node_t **meshlink_get_all_nodes_by_last_reachable(meshlink_handle_t *mesh, time_t start, time_t end, meshlink_node_t **nodes, size_t *nmemb) { - if(!mesh || !nmemb) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - struct time_range range = {start, end}; - - return meshlink_get_all_nodes_by_condition(mesh, &range, nodes, nmemb, search_node_by_last_reachable); -} - dev_class_t meshlink_get_node_dev_class(meshlink_handle_t *mesh, meshlink_node_t *node) { if(!mesh || !node) { meshlink_errno = MESHLINK_EINVAL; @@ -2387,13 +2308,9 @@ bool meshlink_get_node_reachability(struct meshlink_handle *mesh, struct meshlin reachable = n->status.reachable && !n->status.blacklisted; - if(last_reachable) { - *last_reachable = n->last_reachable; - } - - if(last_unreachable) { - *last_unreachable = n->last_unreachable; - } + // TODO: handle reachable times? + (void)last_reachable; + (void)last_unreachable; pthread_mutex_unlock(&mesh->mutex); @@ -3075,10 +2992,6 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) { break; } - /* Clear the reachability times, since we ourself have never seen these nodes yet */ - n->last_reachable = 0; - n->last_unreachable = 0; - if(!node_write_config(mesh, n, true)) { free_node(n); free(buf); @@ -4049,36 +3962,6 @@ void handle_duplicate_node(meshlink_handle_t *mesh, node_t *n) { mesh->node_duplicate_cb(mesh, (meshlink_node_t *)n); } -void meshlink_enable_discovery(meshlink_handle_t *mesh, bool enable) { - logger(mesh, MESHLINK_DEBUG, "meshlink_enable_discovery(%d)", enable); - - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return; - } - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - if(mesh->discovery.enabled == enable) { - goto end; - } - - if(mesh->threadstarted) { - if(enable) { - discovery_start(mesh); - } else { - discovery_stop(mesh); - } - } - - mesh->discovery.enabled = enable; - -end: - pthread_mutex_unlock(&mesh->mutex); -} - void meshlink_hint_network_change(struct meshlink_handle *mesh) { logger(mesh, MESHLINK_DEBUG, "meshlink_hint_network_change()"); @@ -4091,15 +3974,6 @@ void meshlink_hint_network_change(struct meshlink_handle *mesh) { abort(); } - if(mesh->discovery.enabled) { - scan_ifaddrs(mesh); - } - - if(mesh->loop.now.tv_sec > mesh->discovery.last_update + 5) { - mesh->discovery.last_update = mesh->loop.now.tv_sec; - handle_network_change(mesh, 1); - } - pthread_mutex_unlock(&mesh->mutex); } @@ -4180,10 +4054,6 @@ void meshlink_reset_timers(struct meshlink_handle *mesh) { handle_network_change(mesh, true); - if(mesh->discovery.enabled) { - discovery_refresh(mesh); - } - pthread_mutex_unlock(&mesh->mutex); } @@ -4203,28 +4073,6 @@ void meshlink_set_inviter_commits_first(struct meshlink_handle *mesh, bool invit pthread_mutex_unlock(&mesh->mutex); } -void meshlink_set_external_address_discovery_url(struct meshlink_handle *mesh, const char *url) { - logger(mesh, MESHLINK_DEBUG, "meshlink_set_external_address_discovery_url(%s)", url ? url : "(null)"); - - if(!mesh) { - meshlink_errno = EINVAL; - return; - } - - if(url && (strncmp(url, "http://", 7) || strchr(url, ' '))) { - meshlink_errno = EINVAL; - return; - } - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - free(mesh->external_address_url); - mesh->external_address_url = url ? xstrdup(url) : NULL; - pthread_mutex_unlock(&mesh->mutex); -} - void meshlink_set_scheduling_granularity(struct meshlink_handle *mesh, long granularity) { logger(mesh, MESHLINK_DEBUG, "meshlink_set_scheduling_granularity(%ld)", granularity); diff --git a/src/meshlink.sym b/src/meshlink.sym index acb8525..f6cd014 100644 --- a/src/meshlink.sym +++ b/src/meshlink.sym @@ -1,6 +1,4 @@ __emutls_v.meshlink_errno -devtool_export_json_all_edges_state -devtool_get_all_edges devtool_get_all_submeshes devtool_get_node_status devtool_keyrotate_probe @@ -28,7 +26,6 @@ meshlink_clear_canonical_address meshlink_close meshlink_destroy meshlink_destroy_ex -meshlink_enable_discovery meshlink_encrypted_key_rotate meshlink_errno meshlink_export @@ -81,7 +78,6 @@ meshlink_set_dev_class_fast_retry_period meshlink_set_dev_class_maxtimeout meshlink_set_dev_class_timeouts meshlink_set_error_cb -meshlink_set_external_address_discovery_url meshlink_set_inviter_commits_first meshlink_set_log_cb meshlink_set_node_channel_timeout diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index af3a250..1084911 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -47,7 +47,6 @@ static const char meshlink_udp_label[] = "MeshLink UDP"; typedef struct listen_socket_t { struct io_t tcp; - struct io_t udp; sockaddr_t sa; sockaddr_t broadcast_sa; } listen_socket_t; @@ -100,10 +99,7 @@ struct meshlink_handle { meshlink_queue_t outpacketqueue; signal_t datafromapp; - hash_t *node_udp_cache; - struct splay_tree_t *nodes; - struct splay_tree_t *edges; struct list_t *connections; struct list_t *outgoings; @@ -148,8 +144,6 @@ struct meshlink_handle { dev_class_t devclass; - int udp_choice; - dev_class_traits_t dev_class_traits[DEV_CLASS_COUNT]; int netns; @@ -168,22 +162,6 @@ struct meshlink_handle { pthread_cond_t cond; bool threadstarted; - // mDNS discovery - struct { - bool enabled; - io_t pfroute_io; - int *ifaces; - struct discovery_address *addresses; - int iface_count; - int address_count; - io_t sockets[2]; - time_t last_update; -#ifdef __APPLE__ - pthread_t thread; - void *runloop; -#endif - } discovery; - // ADNS pthread_t adns_thread; pthread_cond_t adns_cond; diff --git a/src/net.c b/src/net.c index 35cfc65..60c16cb 100644 --- a/src/net.c +++ b/src/net.c @@ -23,7 +23,6 @@ #include "conf.h" #include "connection.h" #include "devtools.h" -#include "graph.h" #include "logger.h" #include "meshlink_internal.h" #include "meta.h" @@ -47,11 +46,12 @@ static const int default_interval = 60; /* Terminate a connection: - Mark it as inactive - - Remove the edge representing this connection - Kill it with fire - Check if we need to retry making an outgoing connection */ void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report) { + (void)report; + if(c->status.active) { logger(mesh, MESHLINK_INFO, "Closing connection with %s", c->name); } @@ -66,31 +66,6 @@ void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report) c->status.active = false; - if(c->edge) { - if(report) { - send_del_edge(mesh, mesh->everyone, c->edge, 0); - } - - edge_del(mesh, c->edge); - c->edge = NULL; - - /* Run MST and SSSP algorithms */ - - graph(mesh); - - /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */ - - if(report && c->node && !c->node->status.reachable) { - edge_t *e; - e = lookup_edge(c->node, mesh->self); - - if(e) { - send_del_edge(mesh, mesh->everyone, e, 0); - edge_del(mesh, e); - } - } - } - outgoing_t *outgoing = c->outgoing; connection_del(mesh, c); diff --git a/src/net.h b/src/net.h index 9994fac..34bb54c 100644 --- a/src/net.h +++ b/src/net.h @@ -89,7 +89,6 @@ void finish_connecting(struct meshlink_handle *mesh, struct connection_t *); void do_outgoing_connection(struct meshlink_handle *mesh, struct outgoing_t *); void handle_new_meta_connection(struct event_loop_t *loop, void *, int); int setup_tcp_listen_socket(struct meshlink_handle *mesh, const struct addrinfo *aip) __attribute__((__warn_unused_result__)); -int setup_udp_listen_socket(struct meshlink_handle *mesh, const struct addrinfo *aip) __attribute__((__warn_unused_result__)); bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len); bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len) __attribute__((__warn_unused_result__)); void send_packet(struct meshlink_handle *mesh, struct node_t *, struct vpn_packet_t *); diff --git a/src/net_packet.c b/src/net_packet.c index 02a617d..b6478e4 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -22,7 +22,6 @@ #include "conf.h" #include "connection.h" #include "crypto.h" -#include "graph.h" #include "logger.h" #include "meshlink_internal.h" #include "net.h" @@ -34,202 +33,6 @@ int keylifetime = 0; -static void send_udppacket(meshlink_handle_t *mesh, node_t *, vpn_packet_t *); - -#define MAX_SEQNO 1073741824 - -/* mtuprobes == 1..30: initial discovery, send bursts with 1 second interval - mtuprobes == 31: sleep pinginterval seconds - mtuprobes == 32: send 1 burst, sleep pingtimeout second - mtuprobes == 33: no response from other side, restart PMTU discovery process - - Probes are sent in batches of at least three, with random sizes between the - lower and upper boundaries for the MTU thus far discovered. - - After the initial discovery, a fourth packet is added to each batch with a - size larger than the currently known PMTU, to test if the PMTU has increased. - - In case local discovery is enabled, another packet is added to each batch, - which will be broadcast to the local network. - -*/ - -static void send_mtu_probe_handler(event_loop_t *loop, void *data) { - meshlink_handle_t *mesh = loop->data; - node_t *n = data; - int timeout = 1; - - n->mtuprobes++; - - if(!n->status.reachable || !n->status.validkey) { - logger(mesh, MESHLINK_INFO, "Trying to send MTU probe to unreachable or rekeying node %s", n->name); - n->mtuprobes = 0; - return; - } - - if(n->mtuprobes > 32) { - if(!n->minmtu) { - n->mtuprobes = 31; - timeout = mesh->dev_class_traits[n->devclass].pinginterval; - goto end; - } - - logger(mesh, MESHLINK_INFO, "%s did not respond to UDP ping, restarting PMTU discovery", n->name); - n->status.udp_confirmed = false; - n->mtuprobes = 1; - n->minmtu = 0; - n->maxmtu = MTU; - - update_node_pmtu(mesh, n); - } - - if(n->mtuprobes >= 10 && n->mtuprobes < 32 && !n->minmtu) { - logger(mesh, MESHLINK_INFO, "No response to MTU probes from %s", n->name); - n->mtuprobes = 31; - } - - if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) { - if(n->minmtu > n->maxmtu) { - n->minmtu = n->maxmtu; - update_node_pmtu(mesh, n); - } else { - n->maxmtu = n->minmtu; - } - - n->mtu = n->minmtu; - logger(mesh, MESHLINK_INFO, "Fixing MTU of %s to %d after %d probes", n->name, n->mtu, n->mtuprobes); - n->mtuprobes = 31; - } - - if(n->mtuprobes == 31) { - if(!n->minmtu && n->status.want_udp && n->nexthop && n->nexthop->connection) { - /* Send a dummy ANS_KEY to try to update the reflexive UDP address */ - send_request(mesh, n->nexthop->connection, NULL, "%d %s %s . -1 -1 -1 0", ANS_KEY, mesh->self->name, n->name); - n->status.want_udp = false; - } - - timeout = mesh->dev_class_traits[n->devclass].pinginterval; - goto end; - } else if(n->mtuprobes == 32) { - timeout = mesh->dev_class_traits[n->devclass].pingtimeout; - } - - for(int i = 0; i < 5; i++) { - int len; - - if(i == 0) { - if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) { - continue; - } - - len = n->maxmtu + 8; - } else if(n->maxmtu <= n->minmtu) { - len = n->maxmtu; - } else { - len = n->minmtu + 1 + prng(mesh, n->maxmtu - n->minmtu); - } - - if(len < 64) { - len = 64; - } - - vpn_packet_t packet; - packet.probe = true; - memset(packet.data, 0, 14); - randomize(packet.data + 14, len - 14); - packet.len = len; - n->status.broadcast = i >= 4 && n->mtuprobes <= 10 && n->prevedge; - - logger(mesh, MESHLINK_DEBUG, "Sending MTU probe length %d to %s", len, n->name); - - send_udppacket(mesh, n, &packet); - } - - n->status.broadcast = false; - -end: - timeout_set(&mesh->loop, &n->mtutimeout, &(struct timespec) { - timeout, prng(mesh, TIMER_FUDGE) - }); -} - -void send_mtu_probe(meshlink_handle_t *mesh, node_t *n) { - timeout_add(&mesh->loop, &n->mtutimeout, send_mtu_probe_handler, n, &(struct timespec) { - 1, 0 - }); - send_mtu_probe_handler(&mesh->loop, n); -} - -static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet, uint16_t len) { - if(len < 64) { - logger(mesh, MESHLINK_WARNING, "Got too short MTU probe length %d from %s", packet->len, n->name); - return; - } - - logger(mesh, MESHLINK_DEBUG, "Got MTU probe length %d from %s", packet->len, n->name); - - if(!packet->data[0]) { - /* It's a probe request, send back a reply */ - - packet->data[0] = 1; - - /* Temporarily set udp_confirmed, so that the reply is sent - back exactly the way it came in. */ - - bool udp_confirmed = n->status.udp_confirmed; - n->status.udp_confirmed = true; - send_udppacket(mesh, n, packet); - n->status.udp_confirmed = udp_confirmed; - } else { - /* It's a valid reply: now we know bidirectional communication - is possible using the address and socket that the reply - packet used. */ - - if(!n->status.udp_confirmed) { - char *address, *port; - sockaddr2str(&n->address, &address, &port); - - if(n->nexthop && n->nexthop->connection) { - send_request(mesh, n->nexthop->connection, NULL, "%d %s %s . -1 -1 -1 0 %s %s", ANS_KEY, n->name, n->name, address, port); - } else { - logger(mesh, MESHLINK_WARNING, "Cannot send reflexive address to %s via %s", n->name, n->nexthop ? n->nexthop->name : n->name); - } - - free(address); - free(port); - n->status.udp_confirmed = true; - } - - /* If we haven't established the PMTU yet, restart the discovery process. */ - - if(n->mtuprobes > 30) { - if(len == n->maxmtu + 8) { - logger(mesh, MESHLINK_INFO, "Increase in PMTU to %s detected, restarting PMTU discovery", n->name); - n->maxmtu = MTU; - n->mtuprobes = 10; - return; - } - - if(n->minmtu) { - n->mtuprobes = 30; - } else { - n->mtuprobes = 1; - } - } - - /* If applicable, raise the minimum supported MTU */ - - if(len > n->maxmtu) { - len = n->maxmtu; - } - - if(n->minmtu < len) { - n->minmtu = len; - update_node_pmtu(mesh, n); - } - } -} - /* VPN packet I/O */ static void receive_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) { @@ -245,33 +48,6 @@ static void receive_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *pac } } -static bool try_mac(meshlink_handle_t *mesh, node_t *n, const vpn_packet_t *inpkt) { - (void)mesh; - return sptps_verify_datagram(&n->sptps, inpkt->data, inpkt->len); -} - -static void receive_udppacket(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *inpkt) { - if(!n->status.reachable) { - logger(mesh, MESHLINK_ERROR, "Got SPTPS data from unreachable node %s", n->name); - return; - } - - if(!n->sptps.state) { - if(!n->status.waitingforkey) { - logger(mesh, MESHLINK_DEBUG, "Got packet from %s but we haven't exchanged keys yet", n->name); - send_req_key(mesh, n); - } else { - logger(mesh, MESHLINK_DEBUG, "Got packet from %s but he hasn't got our key yet", n->name); - } - - return; - } - - if(!sptps_receive_data(&n->sptps, inpkt->data, inpkt->len)) { - logger(mesh, MESHLINK_ERROR, "Could not process SPTPS data from %s: %s", n->name, strerror(errno)); - } -} - static void send_sptps_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *origpkt) { if(!n->status.reachable) { logger(mesh, MESHLINK_ERROR, "Trying to send SPTPS data to unreachable node %s", n->name); @@ -305,107 +81,6 @@ static void send_sptps_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t * return; } -static void choose_udp_address(meshlink_handle_t *mesh, const node_t *n, const sockaddr_t **sa, int *sock, sockaddr_t *sa_buf) { - /* Latest guess */ - *sa = &n->address; - *sock = n->sock; - - /* If the UDP address is confirmed, use it. */ - if(n->status.udp_confirmed) { - return; - } - - /* Send every third packet to n->address; that could be set - to the node's reflexive UDP address discovered during key - exchange. */ - - if(++mesh->udp_choice >= 3) { - mesh->udp_choice = 0; - return; - } - - /* If we have learned an address via Catta, try this once every batch */ - if(mesh->udp_choice == 1 && n->catta_address.sa.sa_family != AF_UNSPEC) { - *sa = &n->catta_address; - goto check_socket; - } - - /* Else, if we have a canonical address, try this once every batch */ - if(mesh->udp_choice == 1 && n->canonical_address) { - char *host = xstrdup(n->canonical_address); - char *port = strchr(host, ' '); - - if(port) { - *port++ = 0; - *sa_buf = str2sockaddr_random(mesh, host, port); - *sa = sa_buf; - - if(sa_buf->sa.sa_family != AF_UNKNOWN) { - free(host); - goto check_socket; - } - } - - free(host); - } - - /* Otherwise, address are found in edges to this node. - So we pick a random edge and a random socket. */ - - edge_t *candidate = NULL; - - { - int i = 0; - int j = prng(mesh, n->edge_tree->count); - - for splay_each(edge_t, e, n->edge_tree) { - if(i++ == j) { - candidate = e->reverse; - break; - } - } - } - - if(candidate) { - *sa = &candidate->address; - *sock = prng(mesh, mesh->listen_sockets); - } - -check_socket: - - /* Make sure we have a suitable socket for the chosen address */ - if(mesh->listen_socket[*sock].sa.sa.sa_family != (*sa)->sa.sa_family) { - for(int i = 0; i < mesh->listen_sockets; i++) { - if(mesh->listen_socket[i].sa.sa.sa_family == (*sa)->sa.sa_family) { - *sock = i; - break; - } - } - } -} - -static void choose_broadcast_address(meshlink_handle_t *mesh, const node_t *n, const sockaddr_t **sa, int *sock) { - *sock = prng(mesh, mesh->listen_sockets); - sockaddr_t *broadcast_sa = &mesh->listen_socket[*sock].broadcast_sa; - - if(broadcast_sa->sa.sa_family == AF_INET6) { - broadcast_sa->in6.sin6_port = n->prevedge->address.in.sin_port; - } else { - broadcast_sa->in.sin_port = n->prevedge->address.in.sin_port; - } - - *sa = broadcast_sa; -} - -static void send_udppacket(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *origpkt) { - if(!n->status.reachable) { - logger(mesh, MESHLINK_INFO, "Trying to send UDP packet to unreachable node %s", n->name); - return; - } - - send_sptps_packet(mesh, n, origpkt); -} - bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) { assert(handle); assert(data); @@ -419,54 +94,29 @@ bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) { return false; } - /* Send it via TCP if it is a handshake packet, TCPOnly is in use, or this packet is larger than the MTU. */ - - if(type >= SPTPS_HANDSHAKE || (type != PKT_PROBE && (len - 21) > to->minmtu)) { - char buf[len * 4 / 3 + 5]; - b64encode(data, buf, len); - if(!to->nexthop || !to->nexthop->connection) { - logger(mesh, MESHLINK_WARNING, "Unable to forward SPTPS packet to %s via %s", to->name, to->nexthop ? to->nexthop->name : to->name); - return false; - } - - /* If no valid key is known yet, send the packets using ANS_KEY requests, - to ensure we get to learn the reflexive UDP address. */ - if(!to->status.validkey) { - return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, 0); - } else { - return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf); - } + if(type == PKT_PROBE) { + /* Probe packets are not supported. */ + return false; } - /* Otherwise, send the packet via UDP */ + /* Send it via TCP. */ - sockaddr_t sa_buf; - const sockaddr_t *sa; - int sock; + char buf[len * 4 / 3 + 5]; + b64encode(data, buf, len); - if(to->status.broadcast) { - choose_broadcast_address(mesh, to, &sa, &sock); - } else { - choose_udp_address(mesh, to, &sa, &sock, &sa_buf); + if(!to->nexthop || !to->nexthop->connection) { + logger(mesh, MESHLINK_WARNING, "Unable to forward SPTPS packet to %s via %s", to->name, to->nexthop ? to->nexthop->name : to->name); + return false; } - if(sendto(mesh->listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { - if(sockmsgsize(sockerrno)) { - if(to->maxmtu >= len) { - to->maxmtu = len - 1; - } - - if(to->mtu >= len) { - to->mtu = len - 1; - } - } else { - logger(mesh, MESHLINK_WARNING, "Error sending UDP SPTPS packet to %s: %s", to->name, sockstrerror(sockerrno)); - return false; - } + /* If no valid key is known yet, send the packets using ANS_KEY requests, + to ensure we get to learn the reflexive UDP address. */ + if(!to->status.validkey) { + return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, 0); + } else { + return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf); } - - return true; } bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len) { @@ -498,11 +148,8 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t vpn_packet_t inpkt; if(type == PKT_PROBE) { - inpkt.len = len; - inpkt.probe = true; - memcpy(inpkt.data, data, len); - mtu_probe_h(mesh, from, &inpkt, len); - return true; + /* We shouldn't receive any UDP probe packets. */ + return false; } else { inpkt.probe = false; } @@ -549,89 +196,3 @@ void send_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) { send_sptps_packet(mesh, n, packet); return; } - -static node_t *try_harder(meshlink_handle_t *mesh, const sockaddr_t *from, const vpn_packet_t *pkt) { - node_t *n = NULL; - bool hard = false; - - for splay_each(edge_t, e, mesh->edges) { - if(!e->to->status.reachable || e->to == mesh->self) { - continue; - } - - if(sockaddrcmp_noport(from, &e->address)) { - if(mesh->last_hard_try == mesh->loop.now.tv_sec) { - continue; - } - - hard = true; - } - - if(!try_mac(mesh, e->to, pkt)) { - continue; - } - - n = e->to; - break; - } - - if(hard) { - mesh->last_hard_try = mesh->loop.now.tv_sec; - } - - return n; -} - -void handle_incoming_vpn_data(event_loop_t *loop, void *data, int flags) { - (void)flags; - meshlink_handle_t *mesh = loop->data; - listen_socket_t *ls = data; - vpn_packet_t pkt; - char *hostname; - sockaddr_t from; - socklen_t fromlen = sizeof(from); - node_t *n; - int len; - - memset(&from, 0, sizeof(from)); - - len = recvfrom(ls->udp.fd, pkt.data, MAXSIZE, 0, &from.sa, &fromlen); - - if(len <= 0 || len > MAXSIZE) { - if(!sockwouldblock(sockerrno)) { - logger(mesh, MESHLINK_ERROR, "Receiving packet failed: %s", sockstrerror(sockerrno)); - } - - return; - } - - pkt.len = len; - - sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ - - n = lookup_node_udp(mesh, &from); - - if(!n) { - n = try_harder(mesh, &from, &pkt); - - if(n) { - update_node_udp(mesh, n, &from); - } else if(mesh->log_level <= MESHLINK_WARNING) { - hostname = sockaddr2hostname(&from); - logger(mesh, MESHLINK_WARNING, "Received UDP packet from unknown source %s", hostname); - free(hostname); - return; - } else { - return; - } - } - - if(n->status.blacklisted) { - logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name); - return; - } - - n->sock = ls - mesh->listen_socket; - - receive_udppacket(mesh, n, &pkt); -} diff --git a/src/net_setup.c b/src/net_setup.c index a7a538f..7fd760b 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -22,7 +22,6 @@ #include "conf.h" #include "connection.h" #include "ecdsa.h" -#include "graph.h" #include "logger.h" #include "meshlink_internal.h" #include "net.h" @@ -121,16 +120,8 @@ bool node_read_public_key(meshlink_handle_t *mesh, node_t *n) { } } - time_t last_reachable = packmsg_get_int64(&in); - time_t last_unreachable = packmsg_get_int64(&in); - - if(!n->last_reachable) { - n->last_reachable = last_reachable; - } - - if(!n->last_unreachable) { - n->last_unreachable = last_unreachable; - } + packmsg_skip_element(&in); // last_reachable + packmsg_skip_element(&in); // last_unreachable config_free(&config); return true; @@ -212,8 +203,8 @@ bool node_read_from_config(meshlink_handle_t *mesh, node_t *n, const config_t *c } } - n->last_reachable = packmsg_get_int64(&in); - n->last_unreachable = packmsg_get_int64(&in); + packmsg_skip_element(&in); // last_reachable + packmsg_skip_element(&in); // last_unreachable return packmsg_done(&in); } @@ -271,8 +262,8 @@ bool node_write_config(meshlink_handle_t *mesh, node_t *n, bool new_key) { packmsg_add_sockaddr(&out, &n->recent[i]); } - packmsg_add_int64(&out, n->last_reachable); - packmsg_add_int64(&out, n->last_unreachable); + packmsg_add_int64(&out, 0); // last_reachable + packmsg_add_int64(&out, 0); // last_unreachable if(!packmsg_output_ok(&out)) { meshlink_errno = MESHLINK_EINTERNAL; @@ -394,79 +385,6 @@ int setup_tcp_listen_socket(meshlink_handle_t *mesh, const struct addrinfo *aip) return nfd; } -int setup_udp_listen_socket(meshlink_handle_t *mesh, const struct addrinfo *aip) { - int nfd = socket(aip->ai_family, SOCK_DGRAM, IPPROTO_UDP); - - if(nfd == -1) { - return -1; - } - -#ifdef FD_CLOEXEC - fcntl(nfd, F_SETFD, FD_CLOEXEC); -#endif - -#ifdef O_NONBLOCK - int flags = fcntl(nfd, F_GETFL); - - if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { - closesocket(nfd); - logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "fcntl", strerror(errno)); - return -1; - } - -#elif defined(WIN32) - unsigned long arg = 1; - - if(ioctlsocket(nfd, FIONBIO, &arg) != 0) { - closesocket(nfd); - logger(mesh, MESHLINK_ERROR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno)); - return -1; - } - -#endif - - int option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option)); - setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option)); - -#if defined(IPV6_V6ONLY) - - if(aip->ai_family == AF_INET6) { - setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); - } - -#endif - -#if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT) -#define IP_DONTFRAGMENT IP_DONTFRAG -#endif - -#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) - option = IP_PMTUDISC_DO; - setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option)); -#elif defined(IP_DONTFRAGMENT) - option = 1; - setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option)); -#endif - - if(aip->ai_family == AF_INET6) { -#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) - option = IPV6_PMTUDISC_DO; - setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option)); -#elif defined(IPV6_DONTFRAG) - option = 1; - setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option)); -#endif - } - - if(bind(nfd, aip->ai_addr, aip->ai_addrlen)) { - closesocket(nfd); - return -1; - } - - return nfd; -} - /* Add listening sockets. */ @@ -523,18 +441,7 @@ static bool add_listen_sockets(meshlink_handle_t *mesh) { } } - /* If TCP worked, then we require that UDP works as well. */ - - int udp_fd = setup_udp_listen_socket(mesh, aip); - - if(udp_fd == -1) { - closesocket(tcp_fd); - success = false; - break; - } - io_add(&mesh->loop, &mesh->listen_socket[mesh->listen_sockets].tcp, handle_new_meta_connection, &mesh->listen_socket[mesh->listen_sockets], tcp_fd, IO_READ); - io_add(&mesh->loop, &mesh->listen_socket[mesh->listen_sockets].udp, handle_incoming_vpn_data, &mesh->listen_socket[mesh->listen_sockets], udp_fd, IO_READ); if(mesh->log_level <= MESHLINK_INFO) { char *hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); @@ -562,9 +469,7 @@ static bool add_listen_sockets(meshlink_handle_t *mesh) { if(!success) { for(int i = 0; i < mesh->listen_sockets; i++) { io_del(&mesh->loop, &mesh->listen_socket[i].tcp); - io_del(&mesh->loop, &mesh->listen_socket[i].udp); closesocket(mesh->listen_socket[i].tcp.fd); - closesocket(mesh->listen_socket[i].udp.fd); } mesh->listen_sockets = 0; @@ -626,7 +531,6 @@ bool setup_network(meshlink_handle_t *mesh) { init_connections(mesh); init_submeshes(mesh); init_nodes(mesh); - init_edges(mesh); init_requests(mesh); if(!setup_myself(mesh)) { @@ -651,13 +555,10 @@ void close_network_connections(meshlink_handle_t *mesh) { for(int i = 0; i < mesh->listen_sockets; i++) { io_del(&mesh->loop, &mesh->listen_socket[i].tcp); - io_del(&mesh->loop, &mesh->listen_socket[i].udp); closesocket(mesh->listen_socket[i].tcp.fd); - closesocket(mesh->listen_socket[i].udp.fd); } exit_requests(mesh); - exit_edges(mesh); exit_nodes(mesh); exit_submeshes(mesh); exit_connections(mesh); diff --git a/src/net_socket.c b/src/net_socket.c index 4989b6c..29e3725 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -174,44 +174,6 @@ static void handle_meta_io(event_loop_t *loop, void *data, int flags) { } } -// Find edges pointing to this node, and use them to build a list of unique, known addresses. -static struct addrinfo *get_known_addresses(node_t *n) { - struct addrinfo *ai = NULL; - - for splay_each(edge_t, e, n->edge_tree) { - if(!e->reverse) { - continue; - } - - bool found = false; - - for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { - if(!sockaddrcmp(&e->reverse->address, (sockaddr_t *)aip->ai_addr)) { - found = true; - break; - } - } - - if(found) { - continue; - } - - // Create a new struct addrinfo, and put it at the head of the list. - struct addrinfo *nai = xzalloc(sizeof(*nai) + SALEN(e->reverse->address.sa)); - nai->ai_next = ai; - ai = nai; - - ai->ai_family = e->reverse->address.sa.sa_family; - ai->ai_socktype = SOCK_STREAM; - ai->ai_protocol = IPPROTO_TCP; - ai->ai_addrlen = SALEN(e->reverse->address.sa); - ai->ai_addr = (struct sockaddr *)(nai + 1); - memcpy(ai->ai_addr, &e->reverse->address, ai->ai_addrlen); - } - - return ai; -} - // Build a list of recently seen addresses. static struct addrinfo *get_recent_addresses(node_t *n) { struct addrinfo *ai = NULL; @@ -339,24 +301,6 @@ static bool get_next_outgoing_address(meshlink_handle_t *mesh, outgoing_t *outgo return true; } - free_known_addresses(outgoing->ai); - outgoing->ai = NULL; - outgoing->aip = NULL; - outgoing->state = OUTGOING_KNOWN; - } - - if(outgoing->state == OUTGOING_KNOWN) { - if(!outgoing->aip) { - outgoing->ai = get_known_addresses(outgoing->node); - outgoing->aip = outgoing->ai; - } else { - outgoing->aip = outgoing->aip->ai_next; - } - - if(outgoing->aip) { - return true; - } - free_known_addresses(outgoing->ai); outgoing->ai = NULL; outgoing->aip = NULL; diff --git a/src/node.c b/src/node.c index b8caed6..160bcb3 100644 --- a/src/node.c +++ b/src/node.c @@ -35,26 +35,19 @@ static int node_compare(const node_t *a, const node_t *b) { void init_nodes(meshlink_handle_t *mesh) { mesh->nodes = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node); - mesh->node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t)); } void exit_nodes(meshlink_handle_t *mesh) { - if(mesh->node_udp_cache) { - hash_free(mesh->node_udp_cache); - } - if(mesh->nodes) { splay_delete_tree(mesh->nodes); } - mesh->node_udp_cache = NULL; mesh->nodes = NULL; } node_t *new_node(void) { node_t *n = xzalloc(sizeof(*n)); - n->edge_tree = new_edge_tree(); n->mtu = MTU; n->maxmtu = MTU; n->devclass = DEV_CLASS_UNKNOWN; @@ -67,10 +60,6 @@ void free_node(node_t *n) { utcp_exit(n->utcp); - if(n->edge_tree) { - free_edge_tree(n->edge_tree); - } - sockaddrfree(&n->address); ecdsa_free(n->ecdsa); @@ -93,11 +82,6 @@ void node_add(meshlink_handle_t *mesh, 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(mesh, e); - } - splay_delete(mesh->nodes, n); } @@ -110,41 +94,6 @@ node_t *lookup_node(meshlink_handle_t *mesh, const char *name) { return result; } -node_t *lookup_node_udp(meshlink_handle_t *mesh, const sockaddr_t *sa) { - return hash_search(mesh->node_udp_cache, sa); -} - -void update_node_udp(meshlink_handle_t *mesh, node_t *n, const sockaddr_t *sa) { - if(n == mesh->self) { - logger(mesh, MESHLINK_WARNING, "Trying to update UDP address of mesh->self!"); - return; - } - - hash_insert(mesh->node_udp_cache, &n->address, NULL); - - if(sa) { - n->address = *sa; - n->sock = 0; - - for(int i = 0; i < mesh->listen_sockets; i++) { - if(mesh->listen_socket[i].sa.sa.sa_family == sa->sa.sa_family) { - n->sock = i; - break; - } - } - - hash_insert(mesh->node_udp_cache, sa, n); - - node_add_recent_address(mesh, n, sa); - - if(mesh->log_level <= MESHLINK_DEBUG) { - char *hostname = sockaddr2hostname(&n->address); - logger(mesh, MESHLINK_DEBUG, "UDP address of %s set to %s", n->name, hostname); - free(hostname); - } - } -} - bool node_add_recent_address(meshlink_handle_t *mesh, node_t *n, const sockaddr_t *sa) { (void)mesh; bool found = false; diff --git a/src/node.h b/src/node.h index 63f3c2c..26d868d 100644 --- a/src/node.h +++ b/src/node.h @@ -88,15 +88,7 @@ typedef struct node_t { sockaddr_t recent[MAX_RECENT]; /* Recently seen addresses */ sockaddr_t catta_address; /* Latest address seen by Catta */ - // Graph-related member variables - time_t last_reachable; - time_t last_unreachable; - - int distance; struct node_t *nexthop; /* nearest node from us to him */ - struct edge_t *prevedge; /* nearest node from him to us */ - - struct splay_tree_t *edge_tree; /* Edges with this node as one of the endpoints */ } node_t; void init_nodes(struct meshlink_handle *mesh); @@ -106,8 +98,6 @@ void free_node(node_t *n); void node_add(struct meshlink_handle *mesh, node_t *n); void node_del(struct meshlink_handle *mesh, node_t *n); node_t *lookup_node(struct meshlink_handle *mesh, const char *name) __attribute__((__warn_unused_result__)); -node_t *lookup_node_udp(struct meshlink_handle *mesh, const sockaddr_t *sa) __attribute__((__warn_unused_result__)); -void update_node_udp(struct meshlink_handle *mesh, node_t *n, const sockaddr_t *sa); bool node_add_recent_address(struct meshlink_handle *mesh, node_t *n, const sockaddr_t *addr); #endif diff --git a/src/protocol.h b/src/protocol.h index fb1e109..5882513 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -70,7 +70,6 @@ typedef struct past_request_t { #define MAX_STRING_SIZE 2049 #define MAX_STRING "%2048s" -#include "edge.h" #include "net.h" #include "node.h" @@ -92,8 +91,6 @@ bool send_ack(struct meshlink_handle *mesh, struct connection_t *); bool send_error(struct meshlink_handle *mesh, struct connection_t *, request_error_t, const char *); bool send_ping(struct meshlink_handle *mesh, struct connection_t *); bool send_pong(struct meshlink_handle *mesh, struct connection_t *); -bool send_add_edge(struct meshlink_handle *mesh, struct connection_t *, const struct edge_t *, int contradictions); -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 *); diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 943040e..e292d58 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -23,8 +23,6 @@ #include "connection.h" #include "devtools.h" #include "ecdsa.h" -#include "edge.h" -#include "graph.h" #include "logger.h" #include "meshlink_internal.h" #include "meta.h" @@ -148,16 +146,6 @@ bool send_ack(meshlink_handle_t *mesh, connection_t *c) { return send_request(mesh, c, NULL, "%d %s %d %x", ACK, mesh->myport, mesh->devclass, OPTION_PMTU_DISCOVERY | (PROT_MINOR << 24)); } -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 inner_splay_each(edge_t, e, n->edge_tree) { - send_add_edge(mesh, c, e, 0); - } - } -} - bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { assert(request); assert(*request); @@ -200,10 +188,6 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { n->connection->outgoing = NULL; } - /* Remove the edge before terminating the connection, to prevent a graph update. */ - edge_del(mesh, n->connection->edge); - n->connection->edge = NULL; - terminate_connection(mesh, n->connection, false); } } @@ -248,31 +232,7 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { } } - /* Send him everything we know */ - - send_everything(mesh, c); - - /* Create an edge_t for this connection */ - - assert(devclass >= 0 && devclass < DEV_CLASS_COUNT); - - c->edge = new_edge(); - c->edge->from = mesh->self; - c->edge->to = n; - sockaddrcpy_setport(&c->edge->address, &c->address, atoi(hisport)); - c->edge->weight = mesh->dev_class_traits[devclass].edge_weight; - c->edge->connection = c; - - node_add_recent_address(mesh, n, &c->address); - edge_add(mesh, c->edge); - - /* Notify everyone of the new edge */ - - send_add_edge(mesh, mesh->everyone, c->edge, 0); - - /* Run MST and SSSP algorithms */ - - graph(mesh); + /* TODO: Create an edge_t for this connection, send it */ /* Request a session key to jump start UDP traffic */ diff --git a/src/protocol_edge.c b/src/protocol_edge.c index aa1a648..16ebfd5 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -21,8 +21,6 @@ #include "conf.h" #include "connection.h" -#include "edge.h" -#include "graph.h" #include "logger.h" #include "meshlink_internal.h" #include "meta.h" @@ -34,6 +32,7 @@ #include "xalloc.h" #include "submesh.h" +#if 0 bool send_add_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e, int contradictions) { bool x; char *address, *port; @@ -82,11 +81,15 @@ bool send_add_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e, in return x; } +#endif bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { assert(request); assert(*request); + (void)mesh; + (void)c; +#if 0 edge_t *e; node_t *from, *to; char from_name[MAX_STRING_SIZE]; @@ -255,10 +258,13 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { /* Tell the rest about the new edge */ forward_request(mesh, c, s, request); +#endif + /* TODO: Check if this is an edge we would own */ return true; } +#if 0 bool send_del_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e, int contradictions) { submesh_t *s = NULL; @@ -286,11 +292,15 @@ bool send_del_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e, in return send_request(mesh, c, s, "%d %x %s %s %d %x", DEL_EDGE, prng(mesh, UINT_MAX), e->from->name, e->to->name, contradictions, e->session_id); } +#endif bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { assert(request); assert(*request); + (void)mesh; + (void)c; +#if 0 edge_t *e; char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; @@ -380,5 +390,8 @@ bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { } } +#endif + + /* TODO: Check if this is an edge we would own. */ return true; } diff --git a/src/protocol_key.c b/src/protocol_key.c index 25dbc55..bd27b01 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -411,17 +411,6 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { return false; } - /* Append the known UDP address of the from node, if we have a confirmed one */ - if(!*address && from->status.udp_confirmed && from->address.sa.sa_family != AF_UNSPEC) { - char *reflexive_address, *reflexive_port; - logger(mesh, MESHLINK_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name); - sockaddr2str(&from->address, &reflexive_address, &reflexive_port); - send_request(mesh, to->nexthop->connection, NULL, "%s %s %s", request, reflexive_address, reflexive_port); - free(reflexive_address); - free(reflexive_port); - return true; - } - return send_request(mesh, to->nexthop->connection, NULL, "%s", request); } @@ -429,29 +418,7 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(from == mesh->self) { if(*key == '.' && *address && *port) { - logger(mesh, MESHLINK_DEBUG, "Learned our own reflexive UDP address from %s: %s port %s", c->name, address, port); - - /* Inform all other nodes we want to communicate with and which are reachable via this connection */ - for splay_each(node_t, n, mesh->nodes) { - if(n->nexthop != c->node) { - continue; - } - - if(n->status.udp_confirmed) { - continue; - } - - if(!n->status.waitingforkey && !n->status.validkey) { - continue; - } - - if(!n->nexthop->connection) { - continue; - } - - logger(mesh, MESHLINK_DEBUG, "Forwarding our own reflexive UDP address to %s", n->name); - send_request(mesh, c, NULL, "%d %s %s . -1 -1 -1 0 %s %s", ANS_KEY, mesh->self->name, n->name, address, port); - } + /* Ignore reflexive UDP address */ } else { logger(mesh, MESHLINK_WARNING, "Got %s from %s from %s to %s", "ANS_KEY", c->name, from_name, to_name); @@ -482,12 +449,8 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(from->status.validkey) { if(*address && *port) { - logger(mesh, MESHLINK_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); - sockaddr_t sa = str2sockaddr(address, port); - update_node_udp(mesh, from, &sa); + /* Ignore reflexive UDP address */ } - - send_mtu_probe(mesh, from); } return true; diff --git a/test/basic.c b/test/basic.c index e848efd..1fd39ec 100644 --- a/test/basic.c +++ b/test/basic.c @@ -43,32 +43,12 @@ int main(void) { assert(self); assert(!strcmp(self->name, "foo")); - // Check that we are not reachable. - - time_t last_reachable; - time_t last_unreachable; - assert(!meshlink_get_node_reachability(mesh, self, &last_reachable, &last_unreachable)); - assert(!last_reachable); - assert(!last_unreachable); - // Start and stop the mesh. assert(meshlink_start(mesh)); - // Check that we are now reachable - - assert(meshlink_get_node_reachability(mesh, self, &last_reachable, &last_unreachable)); - assert(last_reachable); - assert(!last_unreachable); - meshlink_stop(mesh); - // Check that we are no longer reachable. - - assert(!meshlink_get_node_reachability(mesh, self, &last_reachable, &last_unreachable)); - assert(last_reachable); - assert(last_unreachable); - // Make sure we can start and stop the mesh again. assert(meshlink_start(mesh)); @@ -92,12 +72,6 @@ int main(void) { assert(!strcmp(mesh->name, "foo")); assert(!strcmp(self->name, "foo")); - // Check that we remembered we were reachable - - assert(!meshlink_get_node_reachability(mesh, self, &last_reachable, &last_unreachable)); - assert(last_reachable); - assert(last_unreachable); - // Check that the name is ignored now, and that we still are "foo". assert(!meshlink_get_node(mesh, "bar")); diff --git a/test/basicpp.cpp b/test/basicpp.cpp index bed6946..06e732c 100644 --- a/test/basicpp.cpp +++ b/test/basicpp.cpp @@ -24,10 +24,6 @@ int main(void) { assert(self); assert(!strcmp(self->name, "foo")); - // Disable local discovery. - - mesh.enable_discovery(false); - // Start and stop the mesh. assert(mesh.start()); @@ -55,8 +51,6 @@ int main(void) { // Start and stop the mesh. - mesh.enable_discovery(false); - assert(mesh.start()); mesh.stop(); } diff --git a/test/channels-aio-fd.c b/test/channels-aio-fd.c index dbfdde6..0917fa8 100644 --- a/test/channels-aio-fd.c +++ b/test/channels-aio-fd.c @@ -102,9 +102,6 @@ int main(void) { mesh_b->priv = in_infos; - meshlink_enable_discovery(mesh_a, false); - meshlink_enable_discovery(mesh_b, false); - // Set the callbacks. meshlink_set_channel_accept_cb(mesh_b, accept_cb); diff --git a/test/channels-fork.c b/test/channels-fork.c index a1089b5..329d131 100644 --- a/test/channels-fork.c +++ b/test/channels-fork.c @@ -84,8 +84,6 @@ static int main1(int rfd, int wfd) { meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.1", "foo", "channels-fork", DEV_CLASS_BACKBONE); assert(mesh); - meshlink_enable_discovery(mesh, false); - assert(meshlink_set_canonical_address(mesh, meshlink_get_self(mesh), "localhost", NULL)); char *data = meshlink_export(mesh); @@ -138,8 +136,6 @@ static int main2(int rfd, int wfd) { meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.2", "bar", "channels-fork", DEV_CLASS_BACKBONE); assert(mesh); - meshlink_enable_discovery(mesh, false); - assert(meshlink_set_canonical_address(mesh, meshlink_get_self(mesh), "localhost", NULL)); char *data = meshlink_export(mesh); diff --git a/test/channels-udp.c b/test/channels-udp.c index c268727..820eb54 100644 --- a/test/channels-udp.c +++ b/test/channels-udp.c @@ -97,7 +97,6 @@ int main(void) { assert(meshlink_destroy("channels_udp_conf.0")); meshlink_handle_t *server = meshlink_open("channels_udp_conf.0", "server", "channels-udp", DEV_CLASS_BACKBONE); assert(server); - meshlink_enable_discovery(server, false); server->priv = channels; meshlink_set_channel_accept_cb(server, accept_cb); assert(meshlink_start(server)); @@ -110,7 +109,6 @@ int main(void) { clients[i].mesh = meshlink_open(dir, names[i], "channels-udp", DEV_CLASS_STATIONARY); assert(clients[i].mesh); clients[i].mesh->priv = &clients[i]; - meshlink_enable_discovery(clients[i].mesh, false); link_meshlink_pair(server, clients[i].mesh); meshlink_set_node_status_cb(clients[i].mesh, status_cb); assert(meshlink_start(clients[i].mesh)); diff --git a/test/duplicate.c b/test/duplicate.c index 6e7607c..0dba67f 100644 --- a/test/duplicate.c +++ b/test/duplicate.c @@ -36,7 +36,6 @@ int main(void) { assert(mesh[i]); assert(meshlink_set_canonical_address(mesh[i], meshlink_get_self(mesh[i]), "localhost", NULL)); - meshlink_enable_discovery(mesh[i], false); meshlink_set_node_duplicate_cb(mesh[i], handle_duplicate); } diff --git a/test/get-all-nodes.c b/test/get-all-nodes.c index 2d68c42..1945058 100644 --- a/test/get-all-nodes.c +++ b/test/get-all-nodes.c @@ -53,19 +53,9 @@ int main(void) { assert(nnodes == 1); assert(nodes[0] == meshlink_get_self(mesh[0])); - // We should never have been online. - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes); - assert(nnodes == 0); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_self(mesh[0])); - // Let nodes know about each other. for(int i = 0; i < 3; i++) { - meshlink_enable_discovery(mesh[i], false); assert(meshlink_set_canonical_address(mesh[i], meshlink_get_self(mesh[i]), "localhost", NULL)); char *data = meshlink_export(mesh[i]); assert(data); @@ -93,37 +83,11 @@ int main(void) { nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_STATIONARY, nodes, &nnodes); assert(nnodes == 2); - // But no node should have been online. - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes); - assert(nnodes == 0); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes); - assert(nnodes == 3); - // Start foo. time_t foo_started = time(NULL); assert(meshlink_start(mesh[0])); - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_self(mesh[0])); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes); - assert(nnodes == 2); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], foo_started - 1, -1, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_self(mesh[0])); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started - 1, nodes, &nnodes); - assert(nnodes == 0); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_self(mesh[0])); - // Start bar and wait for it to connect. meshlink_set_node_status_cb(mesh[0], status_cb); @@ -133,46 +97,15 @@ int main(void) { assert(wait_sync_flag(&bar_reachable, 20)); time_t bar_started = time(NULL); - // Validate time ranges. - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes); - assert(nnodes == 2); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_node(mesh[0], "baz")); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_self(mesh[0])); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes); - assert(nnodes == 2); - assert(nodes[0] == meshlink_get_node(mesh[0], "bar")); - assert(nodes[1] == meshlink_get_self(mesh[0])); - // Stop bar. meshlink_stop(mesh[1]); sleep(2); - time_t bar_stopped = time(NULL); - - // Validate we can see when bar was reachable. - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_stopped, bar_stopped, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_self(mesh[0])); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes); - assert(nnodes == 2); - assert(nodes[0] == meshlink_get_node(mesh[0], "bar")); - assert(nodes[1] == meshlink_get_self(mesh[0])); // Close and restart foo, check that it remembers correctly. meshlink_close(mesh[0]); sleep(2); - time_t foo_stopped = time(NULL); mesh[0] = meshlink_open("get_all_nodes_conf.1", "foo", "get-all_nodes", DEV_CLASS_BACKBONE); assert(mesh[0]); @@ -186,32 +119,6 @@ int main(void) { nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_STATIONARY, nodes, &nnodes); assert(nnodes == 2); - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_node(mesh[0], "baz")); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes); - assert(nnodes == 2); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started - 1, nodes, &nnodes); - assert(nnodes == 0); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_self(mesh[0])); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes); - assert(nnodes == 2); - assert(nodes[0] == meshlink_get_node(mesh[0], "bar")); - assert(nodes[1] == meshlink_get_self(mesh[0])); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_stopped, bar_stopped, nodes, &nnodes); - assert(nnodes == 1); - assert(nodes[0] == meshlink_get_self(mesh[0])); - - nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], foo_stopped, -1, nodes, &nnodes); - assert(nnodes == 0); - // Clean up. for(int i = 0; i < 3; i++) { diff --git a/test/import-export.c b/test/import-export.c index 08343d0..3382fee 100644 --- a/test/import-export.c +++ b/test/import-export.c @@ -48,11 +48,6 @@ int main(void) { meshlink_handle_t *mesh2 = meshlink_open("import_export_conf.2", "bar", "import-export", DEV_CLASS_BACKBONE); assert(mesh2); - // Disable local discovery - - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); - // Import and export both side's data assert(meshlink_set_canonical_address(mesh1, meshlink_get_self(mesh1), "localhost", NULL)); diff --git a/test/invite-join.c b/test/invite-join.c index 9ae831e..e84ddd8 100644 --- a/test/invite-join.c +++ b/test/invite-join.c @@ -72,12 +72,6 @@ int main(void) { meshlink_handle_t *mesh3 = meshlink_open("invite_join_conf.3", "quux", "invite-join", DEV_CLASS_BACKBONE); assert(mesh3); - // Disable local discovery. - - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); - meshlink_enable_discovery(mesh3, false); - // Have the first instance generate invitations. meshlink_set_node_status_cb(mesh1, status_cb); diff --git a/test/netns_utils.c b/test/netns_utils.c index 50f7be8..5e0ed21 100644 --- a/test/netns_utils.c +++ b/test/netns_utils.c @@ -55,8 +55,6 @@ static void create_peers(peer_config_t *peers, int npeers, const char *prefix) { assert(peers[i].mesh); free(params); free(conf_path); - - meshlink_enable_discovery(peers[i].mesh, false); } } diff --git a/test/storage-policy.c b/test/storage-policy.c index 7f757a3..6885406 100644 --- a/test/storage-policy.c +++ b/test/storage-policy.c @@ -25,8 +25,6 @@ int main(void) { mesh2 = meshlink_open("storage-policy_conf.2", "bar", "storage-policy", DEV_CLASS_BACKBONE); assert(mesh1); assert(mesh2); - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); meshlink_set_storage_policy(mesh1, MESHLINK_STORAGE_DISABLED); meshlink_set_storage_policy(mesh2, MESHLINK_STORAGE_DISABLED); @@ -56,8 +54,6 @@ int main(void) { mesh2 = meshlink_open("storage-policy_conf.2", "bar", "storage-policy", DEV_CLASS_BACKBONE); assert(mesh1); assert(mesh2); - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); meshlink_set_storage_policy(mesh1, MESHLINK_STORAGE_KEYS_ONLY); meshlink_set_storage_policy(mesh2, MESHLINK_STORAGE_KEYS_ONLY); @@ -82,8 +78,6 @@ int main(void) { mesh2 = meshlink_open("storage-policy_conf.2", "bar", "storage-policy", DEV_CLASS_BACKBONE); assert(mesh1); assert(mesh2); - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); meshlink_set_storage_policy(mesh1, MESHLINK_STORAGE_KEYS_ONLY); meshlink_set_storage_policy(mesh2, MESHLINK_STORAGE_KEYS_ONLY); @@ -115,8 +109,6 @@ int main(void) { mesh2 = meshlink_open("storage-policy_conf.2", "bar", "storage-policy", DEV_CLASS_BACKBONE); assert(mesh1); assert(mesh2); - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); meshlink_set_storage_policy(mesh1, MESHLINK_STORAGE_KEYS_ONLY); meshlink_set_storage_policy(mesh2, MESHLINK_STORAGE_KEYS_ONLY); @@ -141,8 +133,6 @@ int main(void) { mesh2 = meshlink_open("storage-policy_conf.2", "bar", "storage-policy", DEV_CLASS_BACKBONE); assert(mesh1); assert(mesh2); - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); assert(!meshlink_get_node_reachability(mesh1, meshlink_get_node(mesh1, "bar"), &last_reachable, &last_unreachable)); assert(last_reachable); @@ -156,8 +146,6 @@ int main(void) { mesh2 = meshlink_open("storage-policy_conf.2", "bar", "storage-policy", DEV_CLASS_BACKBONE); assert(mesh1); assert(mesh2); - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); meshlink_set_storage_policy(mesh1, MESHLINK_STORAGE_KEYS_ONLY); meshlink_set_storage_policy(mesh2, MESHLINK_STORAGE_KEYS_ONLY); diff --git a/test/trio.c b/test/trio.c index 292a1a5..5b5a612 100644 --- a/test/trio.c +++ b/test/trio.c @@ -119,13 +119,6 @@ int main(void) { assert(wait_sync_flag(&received, 15)); - // Check that the second and third node have autoconnected to each other - - devtool_edge_t *edges = NULL; - size_t nedges = 0; - assert_after((edges = devtool_get_all_edges(mesh[1], edges, &nedges), nedges == 3), 15); - free(edges); - // Stop the first node meshlink_stop(mesh[0]); diff --git a/test/trio2.c b/test/trio2.c index cc1ce87..c59aa64 100644 --- a/test/trio2.c +++ b/test/trio2.c @@ -105,13 +105,6 @@ int main(void) { assert(wait_sync_flag(&bar_learned_baz, 5)); assert(wait_sync_flag(&baz_learned_bar, 5)); - // Check that the second and third node autoconnect to each other - - devtool_edge_t *edges = NULL; - size_t nedges = 0; - assert_after((edges = devtool_get_all_edges(mesh[1], edges, &nedges), nedges == 3), 15); - free(edges); - // Stop the nodes nodes for(int i = 0; i < 3; i++) { diff --git a/test/utils.c b/test/utils.c index 872060b..27582ad 100644 --- a/test/utils.c +++ b/test/utils.c @@ -100,9 +100,6 @@ void open_meshlink_pair(meshlink_handle_t **pa, meshlink_handle_t **pb, const ch free(a_name); free(b_name); - meshlink_enable_discovery(a, false); - meshlink_enable_discovery(b, false); - link_meshlink_pair(a, b); *pa = a; @@ -120,9 +117,6 @@ void open_meshlink_pair_ephemeral(meshlink_handle_t **pa, meshlink_handle_t **pb assert(a); assert(b); - meshlink_enable_discovery(a, false); - meshlink_enable_discovery(b, false); - link_meshlink_pair(a, b); *pa = a;