X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fmeshlink.c;h=b85795d465e3c64c59bc6c0990f3deb60dfd3f86;hb=fe7be9e345bcc652914ef6fc51302da13d4c9c8d;hp=3242bc267d625a34686e06804cb4efa925fcd652;hpb=963c5055505f2fc117cd5efa06eaa02c9b2bf85d;p=meshlink diff --git a/src/meshlink.c b/src/meshlink.c index 3242bc26..b85795d4 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -20,6 +20,7 @@ #include "system.h" #include +#include "adns.h" #include "crypto.h" #include "ecdsagen.h" #include "logger.h" @@ -172,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) { @@ -255,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; @@ -499,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; } @@ -516,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 @@ -705,24 +665,28 @@ static bool finalize_join(join_state_t *state, const void *buf, uint16_t len) { } char *name = packmsg_get_str_dup(&in); - packmsg_skip_element(&in); /* submesh */ + char *submesh_name = packmsg_get_str_dup(&in); dev_class_t devclass = packmsg_get_int32(&in); uint32_t count = packmsg_get_array(&in); - if(!name) { - logger(mesh, MESHLINK_DEBUG, "No Name found in invitation!\n"); + if(!name || !check_id(name)) { + logger(mesh, MESHLINK_DEBUG, "No valid Name found in invitation!\n"); + free(name); + free(submesh_name); return false; } - if(!check_id(name)) { - logger(mesh, MESHLINK_DEBUG, "Invalid Name found in invitation: %s!\n", name); + if(!submesh_name || (strcmp(submesh_name, CORE_MESH) && !check_id(submesh_name))) { + logger(mesh, MESHLINK_DEBUG, "No valid Submesh found in invitation!\n"); free(name); + free(submesh_name); return false; } if(!count) { logger(mesh, MESHLINK_ERROR, "Incomplete invitation file!\n"); free(name); + free(submesh_name); return false; } @@ -730,6 +694,8 @@ static bool finalize_join(join_state_t *state, const void *buf, uint16_t len) { free(mesh->self->name); mesh->name = name; mesh->self->name = xstrdup(name); + mesh->self->submesh = strcmp(submesh_name, CORE_MESH) ? lookup_or_create_submesh(mesh, submesh_name) : NULL; + free(submesh_name); mesh->self->devclass = devclass == DEV_CLASS_UNKNOWN ? mesh->devclass : devclass; // Initialize configuration directory @@ -1123,9 +1089,6 @@ static bool meshlink_read_config(meshlink_handle_t *mesh) { return false; } -#if 0 - - // TODO: check this? if(mesh->name && strcmp(mesh->name, name)) { logger(NULL, MESHLINK_ERROR, "Configuration is for a different name (%s)!", name); meshlink_errno = MESHLINK_ESTORAGE; @@ -1134,8 +1097,6 @@ static bool meshlink_read_config(meshlink_handle_t *mesh) { return false; } -#endif - free(mesh->name); mesh->name = name; xasprintf(&mesh->myport, "%u", myport); @@ -1193,13 +1154,7 @@ meshlink_open_params_t *meshlink_open_params_init(const char *confbase, const ch return NULL; } - if(!name || !*name) { - logger(NULL, MESHLINK_ERROR, "No name given!\n"); - meshlink_errno = MESHLINK_EINVAL; - return NULL; - }; - - if(!check_id(name)) { + if(name && !check_id(name)) { logger(NULL, MESHLINK_ERROR, "Invalid name given!\n"); meshlink_errno = MESHLINK_EINVAL; return NULL; @@ -1214,7 +1169,7 @@ meshlink_open_params_t *meshlink_open_params_init(const char *confbase, const ch meshlink_open_params_t *params = xzalloc(sizeof * params); params->confbase = xstrdup(confbase); - params->name = xstrdup(name); + params->name = name ? xstrdup(name) : NULL; params->appname = xstrdup(appname); params->devclass = devclass; params->netns = -1; @@ -1387,6 +1342,36 @@ meshlink_handle_t *meshlink_open_encrypted(const char *confbase, const char *nam } meshlink_handle_t *meshlink_open_ephemeral(const char *name, const char *appname, dev_class_t devclass) { + if(!name) { + logger(NULL, MESHLINK_ERROR, "No name given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + + if(!check_id(name)) { + logger(NULL, MESHLINK_ERROR, "Invalid name given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + + if(!appname || !*appname) { + logger(NULL, MESHLINK_ERROR, "No appname given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + + if(strchr(appname, ' ')) { + logger(NULL, MESHLINK_ERROR, "Invalid appname given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + + if(devclass < 0 || devclass >= DEV_CLASS_COUNT) { + logger(NULL, MESHLINK_ERROR, "Invalid devclass given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + /* Create a temporary struct on the stack, to avoid allocating and freeing one. */ meshlink_open_params_t params; memset(¶ms, 0, sizeof(params)); @@ -1400,11 +1385,9 @@ meshlink_handle_t *meshlink_open_ephemeral(const char *name, const char *appname } meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { - // Validate arguments provided by the application - bool usingname = false; - logger(NULL, MESHLINK_DEBUG, "meshlink_open called\n"); + // Validate arguments provided by the application if(!params->appname || !*params->appname) { logger(NULL, MESHLINK_ERROR, "No appname given!\n"); meshlink_errno = MESHLINK_EINVAL; @@ -1417,18 +1400,10 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { return NULL; } - if(!params->name || !*params->name) { - logger(NULL, MESHLINK_ERROR, "No name given!\n"); - //return NULL; - } else { //check name only if there is a name != NULL - - if(!check_id(params->name)) { - logger(NULL, MESHLINK_ERROR, "Invalid name given!\n"); - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } else { - usingname = true; - } + if(params->name && !check_id(params->name)) { + logger(NULL, MESHLINK_ERROR, "Invalid name given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; } if(params->devclass < 0 || params->devclass >= DEV_CLASS_COUNT) { @@ -1467,9 +1442,7 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { memcpy(mesh->dev_class_traits, default_class_traits, sizeof(default_class_traits)); - if(usingname) { - mesh->name = xstrdup(params->name); - } + mesh->name = params->name ? xstrdup(params->name) : NULL; // Hash the key if(params->key) { @@ -1504,6 +1477,13 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { // If no configuration exists yet, create it. if(!meshlink_confbase_exists(mesh)) { + if(!mesh->name) { + logger(NULL, MESHLINK_ERROR, "No configuration files found!\n"); + meshlink_close(mesh); + meshlink_errno = MESHLINK_ESTORAGE; + return NULL; + } + if(!meshlink_setup(mesh)) { logger(NULL, MESHLINK_ERROR, "Cannot create initial configuration\n"); meshlink_close(mesh); @@ -1673,6 +1653,7 @@ bool meshlink_start(meshlink_handle_t *mesh) { } init_outgoings(mesh); + init_adns(mesh); // Start the main thread @@ -1743,6 +1724,7 @@ void meshlink_stop(meshlink_handle_t *mesh) { } } + exit_adns(mesh); exit_outgoings(mesh); // Ensure we are considered unreachable @@ -2442,13 +2424,20 @@ bool meshlink_set_canonical_address(meshlink_handle_t *mesh, meshlink_node_t *no } if(!is_valid_hostname(address)) { - logger(mesh, MESHLINK_DEBUG, "Invalid character in address: %s\n", address); + logger(mesh, MESHLINK_DEBUG, "Invalid character in address: %s", address); meshlink_errno = MESHLINK_EINVAL; return false; } + if((node_t *)node != mesh->self && !port) { + logger(mesh, MESHLINK_DEBUG, "Missing port number!"); + meshlink_errno = MESHLINK_EINVAL; + return false; + + } + if(port && !is_valid_port(port)) { - logger(mesh, MESHLINK_DEBUG, "Invalid character in port: %s\n", address); + logger(mesh, MESHLINK_DEBUG, "Invalid character in port: %s", address); meshlink_errno = MESHLINK_EINVAL; return false; } @@ -2892,7 +2881,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) { @@ -3060,7 +3049,15 @@ char *meshlink_export(meshlink_handle_t *mesh) { packmsg_add_int32(&out, mesh->self->devclass); packmsg_add_bool(&out, mesh->self->status.blacklisted); packmsg_add_bin(&out, ecdsa_get_public_key(mesh->private_key), 32); - packmsg_add_str(&out, mesh->self->canonical_address ? mesh->self->canonical_address : ""); + + if(mesh->self->canonical_address && !strchr(mesh->self->canonical_address, ' ')) { + char *canonical_address = NULL; + xasprintf(&canonical_address, "%s %s", mesh->self->canonical_address, mesh->myport); + packmsg_add_str(&out, canonical_address); + free(canonical_address); + } else { + packmsg_add_str(&out, mesh->self->canonical_address ? mesh->self->canonical_address : ""); + } uint32_t count = 0; @@ -4162,6 +4159,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; @@ -4189,6 +4195,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) {