From 86a858b3f9aa659c0d8c411c61f0ac2eeb3a2882 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 19 Jun 2021 17:36:25 +0200 Subject: [PATCH] Remove listening sockets. --- src/meshlink-tiny++.h | 29 ------- src/meshlink-tiny.h | 34 -------- src/meshlink.c | 161 +---------------------------------- src/meshlink.sym | 2 - src/meshlink_internal.h | 8 -- src/net.h | 2 - src/net_setup.c | 182 ---------------------------------------- src/net_socket.c | 89 -------------------- 8 files changed, 1 insertion(+), 506 deletions(-) diff --git a/src/meshlink-tiny++.h b/src/meshlink-tiny++.h index fbe0b29..1a74c29 100644 --- a/src/meshlink-tiny++.h +++ b/src/meshlink-tiny++.h @@ -598,35 +598,6 @@ public: return meshlink_add_external_address(handle); } - /// Get the network port used by the local node. - /** This function returns the network port that the local node is listening on. - * - * @return This function returns the port number, or -1 in case of an error. - */ - int get_port() { - return meshlink_get_port(handle); - } - - /// Set the network port used by the local node. - /** This function sets the network port that the local node is listening on. - * It may only be called when the mesh is not running. - * If unsure, call stop() before calling this function. - * Also note that if your node is already part of a mesh with other nodes, - * that the other nodes may no longer be able to initiate connections to the local node, - * since they will try to connect to the previously configured port. - * - * @param port The port number to listen on. This must be between 0 and 65535. - * If the port is set to 0, then MeshLink will listen on a port - * that is randomly assigned by the operating system every time open() is called. - * - * @return This function returns true if the port was successfully changed - * to the desired port, false otherwise. If it returns false, there - * is no guarantee that MeshLink is listening on the old port. - */ - bool set_port(int port) { - return meshlink_set_port(handle, port); - } - /// 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-tiny.h b/src/meshlink-tiny.h index 0ee3f1a..a13e627 100644 --- a/src/meshlink-tiny.h +++ b/src/meshlink-tiny.h @@ -968,40 +968,6 @@ char *meshlink_get_local_address_for_family(struct meshlink_handle *mesh, int ad */ bool meshlink_add_external_address(struct meshlink_handle *mesh) __attribute__((__warn_unused_result__)); -/// Get the network port used by the local node. -/** This function returns the network port that the local node is listening on. - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - * - * @return This function returns the port number, or -1 in case of an error. - */ -int meshlink_get_port(struct meshlink_handle *mesh) __attribute__((__warn_unused_result__)); - -/// Set the network port used by the local node. -/** This function sets the network port that the local node is listening on. - * It may only be called when the mesh is not running. - * If unsure, call meshlink_stop() before calling this function. - * Also note that if your node is already part of a mesh with other nodes, - * that the other nodes may no longer be able to initiate connections to the local node, - * since they will try to connect to the previously configured port. - * - * Note that if a canonical address has been set for the local node, - * you might need to call meshlink_set_canonical_address() again to ensure it includes the new port number. - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - * @param port The port number to listen on. This must be between 0 and 65535. - * If the port is set to 0, then MeshLink will listen on a port - * that is randomly assigned by the operating system every time meshlink_open() is called. - * - * @return This function returns true if the port was successfully changed - * to the desired port, false otherwise. If it returns false, there - * is no guarantee that MeshLink is listening on the old port. - */ - -bool meshlink_set_port(struct meshlink_handle *mesh, int port) __attribute__((__warn_unused_result__)); - /** This function allows the local node to join an existing mesh using an invitation URL generated by another node. * An invitation can only be used if the local node has never connected to other nodes before. * After a successfully accepted invitation, the name of the local node may have changed. diff --git a/src/meshlink.c b/src/meshlink.c index 9bfaa22..b7379fc 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -428,63 +428,6 @@ char *meshlink_get_local_address_for_family(meshlink_handle_t *mesh, int family) return xstrdup(localaddr); } -static bool try_bind(meshlink_handle_t *mesh, int port) { - struct addrinfo *ai = NULL; - struct addrinfo hint = { - .ai_flags = AI_PASSIVE, - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - }; - - char portstr[16]; - snprintf(portstr, sizeof(portstr), "%d", port); - - if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) { - return false; - } - - bool success = false; - - for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { - /* Try to bind to TCP. */ - - int tcp_fd = setup_tcp_listen_socket(mesh, aip); - - if(tcp_fd == -1) { - if(errno == EADDRINUSE) { - /* If this port is in use for any address family, avoid it. */ - success = false; - break; - } else { - continue; - } - } - - closesocket(tcp_fd); - success = true; - } - - freeaddrinfo(ai); - return success; -} - -int check_port(meshlink_handle_t *mesh) { - for(int i = 0; i < 1000; i++) { - int port = 0x1000 + prng(mesh, 0x8000); - - if(try_bind(mesh, port)) { - free(mesh->myport); - xasprintf(&mesh->myport, "%d", port); - return port; - } - } - - meshlink_errno = MESHLINK_ENETWORK; - logger(mesh, MESHLINK_DEBUG, "Could not find any available network port.\n"); - return 0; -} - static bool write_main_config_files(meshlink_handle_t *mesh) { if(!mesh->confbase) { return true; @@ -911,10 +854,7 @@ static bool meshlink_setup(meshlink_handle_t *mesh) { return false; } - if(check_port(mesh) == 0) { - meshlink_errno = MESHLINK_ENETWORK; - return false; - } + mesh->myport = xstrdup("0"); /* Create a node for ourself */ @@ -1561,18 +1501,11 @@ bool meshlink_start(meshlink_handle_t *mesh) { return true; } - if(mesh->listen_socket[0].tcp.fd < 0) { - logger(mesh, MESHLINK_ERROR, "Listening socket not open\n"); - meshlink_errno = MESHLINK_ENETWORK; - return false; - } - // Reset node connection timers for splay_each(node_t, n, mesh->nodes) { n->last_connect_try = 0; } - // TODO: open listening sockets first //Check that a valid name is set if(!mesh->name) { @@ -2473,98 +2406,6 @@ bool meshlink_add_external_address(meshlink_handle_t *mesh) { return rval; } -int meshlink_get_port(meshlink_handle_t *mesh) { - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return -1; - } - - if(!mesh->myport) { - meshlink_errno = MESHLINK_EINTERNAL; - return -1; - } - - int port; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - port = atoi(mesh->myport); - pthread_mutex_unlock(&mesh->mutex); - - return port; -} - -bool meshlink_set_port(meshlink_handle_t *mesh, int port) { - logger(mesh, MESHLINK_DEBUG, "meshlink_set_port(%d)", port); - - if(!mesh || port < 0 || port >= 65536 || mesh->threadstarted) { - meshlink_errno = MESHLINK_EINVAL; - return false; - } - - if(mesh->myport && port == atoi(mesh->myport)) { - return true; - } - - if(!try_bind(mesh, port)) { - meshlink_errno = MESHLINK_ENETWORK; - return false; - } - - devtool_trybind_probe(); - - bool rval = false; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - if(mesh->threadstarted) { - meshlink_errno = MESHLINK_EINVAL; - goto done; - } - - free(mesh->myport); - xasprintf(&mesh->myport, "%d", port); - - /* Close down the network. This also deletes mesh->self. */ - close_network_connections(mesh); - - /* Recreate mesh->self. */ - mesh->self = new_node(); - mesh->self->name = xstrdup(mesh->name); - mesh->self->devclass = mesh->devclass; - mesh->self->session_id = mesh->session_id; - xasprintf(&mesh->myport, "%d", port); - - if(!node_read_public_key(mesh, mesh->self)) { - logger(NULL, MESHLINK_ERROR, "Could not read our host configuration file!"); - meshlink_errno = MESHLINK_ESTORAGE; - free_node(mesh->self); - mesh->self = NULL; - goto done; - } else if(!setup_network(mesh)) { - meshlink_errno = MESHLINK_ENETWORK; - goto done; - } - - /* Rebuild our own list of recent addresses */ - memset(mesh->self->recent, 0, sizeof(mesh->self->recent)); - add_local_addresses(mesh); - - /* Write meshlink.conf with the updated port number */ - write_main_config_files(mesh); - - rval = config_sync(mesh, "current"); - -done: - pthread_mutex_unlock(&mesh->mutex); - - return rval && meshlink_get_port(mesh) == port; -} - bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { logger(mesh, MESHLINK_DEBUG, "meshlink_join(%s)", invitation ? invitation : "(null)"); diff --git a/src/meshlink.sym b/src/meshlink.sym index f6cd014..d7134a7 100644 --- a/src/meshlink.sym +++ b/src/meshlink.sym @@ -43,7 +43,6 @@ meshlink_get_node_dev_class meshlink_get_node_reachability meshlink_get_node_submesh meshlink_get_pmtu -meshlink_get_port meshlink_get_self meshlink_get_submesh meshlink_hint_address @@ -84,7 +83,6 @@ meshlink_set_node_channel_timeout meshlink_set_node_duplicate_cb meshlink_set_node_pmtu_cb meshlink_set_node_status_cb -meshlink_set_port meshlink_set_receive_cb meshlink_set_scheduling_granularity meshlink_sign diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index 9b506f0..68d061b 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -45,12 +45,6 @@ static const char meshlink_udp_label[] = "MeshLink UDP"; #define MESHLINK_CONFIG_VERSION 2 #define MESHLINK_INVITATION_VERSION 2 -typedef struct listen_socket_t { - struct io_t tcp; - sockaddr_t sa; - sockaddr_t broadcast_sa; -} listen_socket_t; - struct meshlink_open_params { char *confbase; char *lock_filename; @@ -92,8 +86,6 @@ struct meshlink_handle { // The most important network-related members come first int reachable; - int listen_sockets; - listen_socket_t listen_socket[MAXSOCKETS]; meshlink_receive_cb_t receive_cb; meshlink_queue_t outpacketqueue; diff --git a/src/net.h b/src/net.h index 34bb54c..023591b 100644 --- a/src/net.h +++ b/src/net.h @@ -88,7 +88,6 @@ void handle_incoming_vpn_data(struct event_loop_t *loop, void *, int); 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__)); 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 *); @@ -109,7 +108,6 @@ bool node_write_config(struct meshlink_handle *mesh, struct node_t *, bool new_k void send_mtu_probe(struct meshlink_handle *mesh, struct node_t *); void handle_meta_connection_data(struct meshlink_handle *mesh, struct connection_t *); void retry(struct meshlink_handle *mesh); -int check_port(struct meshlink_handle *mesh); void flush_meta(struct meshlink_handle *mesh, struct connection_t *); #ifndef HAVE_MINGW diff --git a/src/net_setup.c b/src/net_setup.c index 7fd760b..b1bfc22 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -328,156 +328,6 @@ static bool load_node(meshlink_handle_t *mesh, const char *name, void *priv) { return true; } -int setup_tcp_listen_socket(meshlink_handle_t *mesh, const struct addrinfo *aip) { - int nfd = socket(aip->ai_family, SOCK_STREAM, IPPROTO_TCP); - - 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)); - -#if defined(IPV6_V6ONLY) - - if(aip->ai_family == AF_INET6) { - setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); - } - -#else -#warning IPV6_V6ONLY not defined -#endif - - if(bind(nfd, aip->ai_addr, aip->ai_addrlen)) { - closesocket(nfd); - return -1; - } - - if(listen(nfd, 3)) { - logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno)); - closesocket(nfd); - return -1; - } - - return nfd; -} - -/* - Add listening sockets. -*/ -static bool add_listen_sockets(meshlink_handle_t *mesh) { - struct addrinfo *ai; - - struct addrinfo hint = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - .ai_flags = AI_PASSIVE | AI_NUMERICSERV, - }; - - int err = getaddrinfo(NULL, mesh->myport, &hint, &ai); - - if(err || !ai) { - logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err)); - return false; - } - - bool success = false; - - for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { - // Ignore duplicate addresses - bool found = false; - - for(int i = 0; i < mesh->listen_sockets; i++) { - if(!memcmp(&mesh->listen_socket[i].sa, aip->ai_addr, aip->ai_addrlen)) { - found = true; - break; - } - } - - if(found) { - continue; - } - - if(mesh->listen_sockets >= MAXSOCKETS) { - logger(mesh, MESHLINK_ERROR, "Too many listening sockets"); - return false; - } - - /* Try to bind to TCP */ - - int tcp_fd = setup_tcp_listen_socket(mesh, aip); - - if(tcp_fd == -1) { - if(errno == EADDRINUSE) { - /* If this port is in use for any address family, avoid it. */ - success = false; - break; - } else { - continue; - } - } - - 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); - - if(mesh->log_level <= MESHLINK_INFO) { - char *hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); - logger(mesh, MESHLINK_INFO, "Listening on %s", hostname); - free(hostname); - } - - memcpy(&mesh->listen_socket[mesh->listen_sockets].sa, aip->ai_addr, aip->ai_addrlen); - memcpy(&mesh->listen_socket[mesh->listen_sockets].broadcast_sa, aip->ai_addr, aip->ai_addrlen); - - if(aip->ai_family == AF_INET6) { - mesh->listen_socket[mesh->listen_sockets].broadcast_sa.in6.sin6_addr.s6_addr[0x0] = 0xff; - mesh->listen_socket[mesh->listen_sockets].broadcast_sa.in6.sin6_addr.s6_addr[0x1] = 0x02; - mesh->listen_socket[mesh->listen_sockets].broadcast_sa.in6.sin6_addr.s6_addr[0xf] = 0x01; - } else { - mesh->listen_socket[mesh->listen_sockets].broadcast_sa.in.sin_addr.s_addr = 0xffffffff; - } - - mesh->listen_sockets++; - success = true; - } - - freeaddrinfo(ai); - - if(!success) { - for(int i = 0; i < mesh->listen_sockets; i++) { - io_del(&mesh->loop, &mesh->listen_socket[i].tcp); - closesocket(mesh->listen_socket[i].tcp.fd); - } - - mesh->listen_sockets = 0; - } - - return success; -} - /* Configure node_t mesh->self and set up the local sockets (listen only) */ @@ -490,33 +340,6 @@ static bool setup_myself(meshlink_handle_t *mesh) { logger(mesh, MESHLINK_WARNING, "Could not scan all host config files"); } - /* Open sockets */ - - mesh->listen_sockets = 0; - - if(!add_listen_sockets(mesh)) { - if(strcmp(mesh->myport, "0")) { - logger(mesh, MESHLINK_WARNING, "Could not bind to port %s, trying to find an alternative port", mesh->myport); - - if(!check_port(mesh)) { - logger(mesh, MESHLINK_WARNING, "Could not bind to any port, trying to bind to port 0"); - free(mesh->myport); - mesh->myport = xstrdup("0"); - } - - if(!add_listen_sockets(mesh)) { - return false; - } - } else { - return false; - } - } - - if(!mesh->listen_sockets) { - logger(mesh, MESHLINK_ERROR, "Unable to create any listening socket!"); - return false; - } - /* Done. */ mesh->last_unreachable = mesh->loop.now.tv_sec; @@ -553,11 +376,6 @@ 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); - closesocket(mesh->listen_socket[i].tcp.fd); - } - exit_requests(mesh); exit_nodes(mesh); exit_submeshes(mesh); diff --git a/src/net_socket.c b/src/net_socket.c index 7f575dc..fe7bf3a 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -40,8 +40,6 @@ #define MSG_NOSIGNAL 0 #endif -static const int max_connection_burst = 100; - /* Setup sockets */ static void configure_tcp(connection_t *c) { @@ -411,93 +409,6 @@ void setup_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) { do_outgoing_connection(mesh, outgoing); } -/// Delayed close of a filedescriptor. -static void tarpit(meshlink_handle_t *mesh, int fd) { - if(!fd) { - return; - } - - if(mesh->pits[mesh->next_pit]) { - closesocket(mesh->pits[mesh->next_pit]); - } - - mesh->pits[mesh->next_pit++] = fd; - - if(mesh->next_pit >= (int)(sizeof mesh->pits / sizeof mesh->pits[0])) { - mesh->next_pit = 0; - } -} - -/* - accept a new tcp connect and create a - new connection -*/ -void handle_new_meta_connection(event_loop_t *loop, void *data, int flags) { - (void)flags; - meshlink_handle_t *mesh = loop->data; - listen_socket_t *l = data; - connection_t *c; - sockaddr_t sa; - int fd; - socklen_t len = sizeof(sa); - - memset(&sa, 0, sizeof(sa)); - - fd = accept(l->tcp.fd, &sa.sa, &len); - - if(fd < 0) { - if(sockwouldblock(errno)) { - return; - } - - if(errno == EINVAL) { // TODO: check if Windows agrees - event_loop_stop(loop); - return; - } - - logger(mesh, MESHLINK_ERROR, "Accepting a new connection failed: %s", sockstrerror(sockerrno)); - return; - } - - sockaddrunmap(&sa); - - /* Rate limit incoming connections to max_connection_burst/second. */ - - if(mesh->loop.now.tv_sec != mesh->connection_burst_time) { - mesh->connection_burst_time = mesh->loop.now.tv_sec; - mesh->connection_burst = 0; - } - - if(mesh->connection_burst >= max_connection_burst) { - tarpit(mesh, fd); - return; - } - - mesh->connection_burst++; - - // Accept the new connection - - c = new_connection(); - c->name = xstrdup(""); - - c->address = sa; - c->socket = fd; - c->last_ping_time = mesh->loop.now.tv_sec; - - char *hostname = sockaddr2hostname(&sa); - logger(mesh, MESHLINK_INFO, "Connection from %s", hostname); - free(hostname); - - io_add(&mesh->loop, &c->io, handle_meta_io, c, c->socket, IO_READ); - - configure_tcp(c); - - connection_add(mesh, c); - - c->allow_request = ID; - send_id(mesh, c); -} - static void free_outgoing(outgoing_t *outgoing) { meshlink_handle_t *mesh = outgoing->node->mesh; -- 2.39.2