X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fmeshlink.c;h=cdf9b17dcd94fe1d77d31a4102b539cf4049f02e;hb=a10895efa0919ff8e00d1ab732a8690fde2786da;hp=fccfecbc404b24e9a9cbfcd67ecce53e221cbeb6;hpb=27b37a02bd75e71ed0a95ab201ba15ef4f5cb588;p=meshlink diff --git a/src/meshlink.c b/src/meshlink.c index fccfecbc..cdf9b17d 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -20,10 +20,12 @@ #include "system.h" #include +#include "adns.h" #include "crypto.h" #include "ecdsagen.h" #include "logger.h" #include "meshlink_internal.h" +#include "net.h" #include "netutl.h" #include "node.h" #include "submesh.h" @@ -171,6 +173,7 @@ static bool getlocaladdr(char *destaddr, sockaddr_t *sa, socklen_t *salen, int n .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, + .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV, }; if(getaddrinfo(destaddr, "80", &hint, &rai) || !rai) { @@ -254,7 +257,7 @@ char *meshlink_get_external_address_for_family(meshlink_handle_t *mesh, int fami } logger(mesh, MESHLINK_DEBUG, "Trying to discover externally visible hostname...\n"); - struct addrinfo *ai = str2addrinfo(host, port ? port : "80", SOCK_STREAM); + struct addrinfo *ai = adns_blocking_request(mesh, xstrdup(host), xstrdup(port ? port : "80"), 5); char line[256]; char *hostname = NULL; @@ -498,15 +501,9 @@ static char *get_my_hostname(meshlink_handle_t *mesh, uint32_t flags) { } // Convert what we have to a sockaddr - struct addrinfo *ai_in, *ai_out; - struct addrinfo hint = { - .ai_family = AF_UNSPEC, - .ai_flags = AI_NUMERICSERV, - .ai_socktype = SOCK_STREAM, - }; - int err = getaddrinfo(hostname[i], port[i], &hint, &ai_in); - - if(err || !ai_in) { + struct addrinfo *ai_in = adns_blocking_request(mesh, xstrdup(hostname[i]), xstrdup(port[i]), 5); + + if(!ai_in) { continue; } @@ -515,44 +512,8 @@ static char *get_my_hostname(meshlink_handle_t *mesh, uint32_t flags) { node_add_recent_address(mesh, mesh->self, (sockaddr_t *)aip->ai_addr); } - if(flags & MESHLINK_INVITE_NUMERIC) { - // We don't need to do any further conversion - freeaddrinfo(ai_in); - continue; - } - - // Convert it to a hostname - char resolved_host[NI_MAXHOST]; - char resolved_port[NI_MAXSERV]; - err = getnameinfo(ai_in->ai_addr, ai_in->ai_addrlen, resolved_host, sizeof resolved_host, resolved_port, sizeof resolved_port, NI_NUMERICSERV); - - if(err || !is_valid_hostname(resolved_host)) { - freeaddrinfo(ai_in); - continue; - } - - // Convert the hostname back to a sockaddr - hint.ai_family = ai_in->ai_family; - err = getaddrinfo(resolved_host, resolved_port, &hint, &ai_out); - - if(err || !ai_out) { - freeaddrinfo(ai_in); - continue; - } - - // Check if it's still the same sockaddr - if(ai_in->ai_addrlen != ai_out->ai_addrlen || memcmp(ai_in->ai_addr, ai_out->ai_addr, ai_in->ai_addrlen)) { - freeaddrinfo(ai_in); - freeaddrinfo(ai_out); - continue; - } - - // Yes: replace the hostname with the resolved one - free(hostname[i]); - hostname[i] = xstrdup(resolved_host); - freeaddrinfo(ai_in); - freeaddrinfo(ai_out); + continue; } // Remove duplicates again, since IPv4 and IPv6 addresses might map to the same hostname @@ -995,10 +956,18 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) { return true; } -static struct timeval idle(event_loop_t *loop, void *data) { +static bool timespec_lt(const struct timespec *a, const struct timespec *b) { + if(a->tv_sec == b->tv_sec) { + return a->tv_nsec < b->tv_nsec; + } else { + return a->tv_sec < b->tv_sec; + } +} + +static struct timespec idle(event_loop_t *loop, void *data) { (void)loop; meshlink_handle_t *mesh = data; - struct timeval t, tmin = {3600, 0}; + struct timespec t, tmin = {3600, 0}; for splay_each(node_t, n, mesh->nodes) { if(!n->utcp) { @@ -1007,7 +976,7 @@ static struct timeval idle(event_loop_t *loop, void *data) { t = utcp_timeout(n->utcp); - if(timercmp(&t, &tmin, <)) { + if(timespec_lt(&t, &tmin)) { tmin = t; } } @@ -1448,6 +1417,7 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { mesh->submeshes = NULL; mesh->log_cb = global_log_cb; mesh->log_level = global_log_level; + mesh->packet = xmalloc(sizeof(vpn_packet_t)); randomize(&mesh->prng_state, sizeof(mesh->prng_state)); @@ -1663,6 +1633,7 @@ bool meshlink_start(meshlink_handle_t *mesh) { } init_outgoings(mesh); + init_adns(mesh); // Start the main thread @@ -1733,6 +1704,7 @@ void meshlink_stop(meshlink_handle_t *mesh) { } } + exit_adns(mesh); exit_outgoings(mesh); // Ensure we are considered unreachable @@ -1797,6 +1769,7 @@ void meshlink_close(meshlink_handle_t *mesh) { free(mesh->confbase); free(mesh->config_key); free(mesh->external_address_url); + free(mesh->packet); ecdsa_free(mesh->private_key); if(mesh->invitation_addresses) { @@ -1954,12 +1927,12 @@ void meshlink_set_error_cb(struct meshlink_handle *mesh, meshlink_error_cb_t cb) pthread_mutex_unlock(&mesh->mutex); } -static vpn_packet_t *prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) { +static bool prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len, vpn_packet_t *packet) { meshlink_packethdr_t *hdr; if(len >= MAXSIZE - sizeof(*hdr)) { meshlink_errno = MESHLINK_EINVAL; - return NULL; + return false; } node_t *n = (node_t *)destination; @@ -1967,17 +1940,10 @@ static vpn_packet_t *prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *de if(n->status.blacklisted) { logger(mesh, MESHLINK_ERROR, "Node %s blacklisted, dropping packet\n", n->name); meshlink_errno = MESHLINK_EBLACKLISTED; - return NULL; + return false; } // Prepare the packet - vpn_packet_t *packet = malloc(sizeof(*packet)); - - if(!packet) { - meshlink_errno = MESHLINK_ENOMEM; - return NULL; - } - packet->probe = false; packet->tcp = false; packet->len = len + sizeof(*hdr); @@ -1991,7 +1957,7 @@ static vpn_packet_t *prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *de memcpy(packet->data + sizeof(*hdr), data, len); - return packet; + return true; } static bool meshlink_send_immediate(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) { @@ -2001,15 +1967,12 @@ static bool meshlink_send_immediate(meshlink_handle_t *mesh, meshlink_node_t *de assert(len); // Prepare the packet - vpn_packet_t *packet = prepare_packet(mesh, destination, data, len); - - if(!packet) { + if(!prepare_packet(mesh, destination, data, len, mesh->packet)) { return false; } // Send it immediately - route(mesh, mesh->self, packet); - free(packet); + route(mesh, mesh->self, mesh->packet); return true; } @@ -2031,12 +1994,17 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const } // Prepare the packet - vpn_packet_t *packet = prepare_packet(mesh, destination, data, len); + vpn_packet_t *packet = malloc(sizeof(*packet)); if(!packet) { + meshlink_errno = MESHLINK_ENOMEM; return false; } + if(!prepare_packet(mesh, destination, data, len, packet)) { + free(packet); + } + // Queue it if(!meshlink_queue_push(&mesh->outpacketqueue, packet)) { free(packet); @@ -2886,7 +2854,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { } // Connect to the meshlink daemon mentioned in the URL. - struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM); + struct addrinfo *ai = adns_blocking_request(mesh, xstrdup(address), xstrdup(port), 5); if(ai) { for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { @@ -3234,7 +3202,7 @@ static bool blacklist(meshlink_handle_t *mesh, node_t *n) { n->status.udp_confirmed = false; if(n->status.reachable) { - n->last_unreachable = mesh->loop.now.tv_sec; + n->last_unreachable = time(NULL); } /* Graph updates will suppress status updates for blacklisted nodes, so we need to @@ -3308,7 +3276,7 @@ static bool whitelist(meshlink_handle_t *mesh, node_t *n) { n->status.blacklisted = false; if(n->status.reachable) { - n->last_reachable = mesh->loop.now.tv_sec; + n->last_reachable = time(NULL); update_node_status(mesh, n); } @@ -3664,6 +3632,7 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac for splay_each(node_t, n, mesh->nodes) { if(!n->utcp && n != mesh->self) { n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); + utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t)); } } @@ -3712,6 +3681,7 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n if(!n->utcp) { n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); + utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t)); mesh->receive_cb = channel_receive; if(!n->utcp) { @@ -3999,6 +3969,15 @@ size_t meshlink_channel_get_recvq(meshlink_handle_t *mesh, meshlink_channel_t *c return utcp_get_recvq(channel->c); } +size_t meshlink_channel_get_mss(meshlink_handle_t *mesh, meshlink_channel_t *channel) { + if(!mesh || !channel) { + meshlink_errno = MESHLINK_EINVAL; + return -1; + } + + return utcp_get_mss(channel->node->utcp); +} + void meshlink_set_node_channel_timeout(meshlink_handle_t *mesh, meshlink_node_t *node, int timeout) { if(!mesh || !node) { meshlink_errno = MESHLINK_EINVAL; @@ -4011,6 +3990,7 @@ void meshlink_set_node_channel_timeout(meshlink_handle_t *mesh, meshlink_node_t if(!n->utcp) { n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); + utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t)); } utcp_set_user_timeout(n->utcp, timeout); @@ -4021,6 +4001,7 @@ void meshlink_set_node_channel_timeout(meshlink_handle_t *mesh, meshlink_node_t void update_node_status(meshlink_handle_t *mesh, node_t *n) { if(n->status.reachable && mesh->channel_accept_cb && !n->utcp) { n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); + utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t)); } if(mesh->node_status_cb) { @@ -4033,6 +4014,8 @@ void update_node_status(meshlink_handle_t *mesh, node_t *n) { } void update_node_pmtu(meshlink_handle_t *mesh, node_t *n) { + utcp_set_mtu(n->utcp, (n->minmtu > MINMTU ? n->minmtu : MINMTU) - sizeof(meshlink_packethdr_t)); + if(mesh->node_pmtu_cb && !n->status.blacklisted) { mesh->node_pmtu_cb(mesh, (meshlink_node_t *)n, n->minmtu); } @@ -4141,6 +4124,15 @@ void meshlink_set_external_address_discovery_url(struct meshlink_handle *mesh, c pthread_mutex_unlock(&mesh->mutex); } +void meshlink_set_scheduling_granularity(struct meshlink_handle *mesh, long granularity) { + if(!mesh || granularity < 0) { + meshlink_errno = EINVAL; + return; + } + + utcp_set_clock_granularity(granularity); +} + void handle_network_change(meshlink_handle_t *mesh, bool online) { (void)online; @@ -4168,6 +4160,7 @@ void call_error_cb(meshlink_handle_t *mesh, meshlink_errno_t meshlink_errno) { static void __attribute__((constructor)) meshlink_init(void) { crypto_init(); + utcp_set_clock_granularity(10000); } static void __attribute__((destructor)) meshlink_exit(void) {