X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fmeshlink.c;h=33af6c36272a4c05aac9c1f1cfab87c0f5f5ccf4;hb=cf5a9d0ff6ef59cd130a865ce1be44b4e8b8471a;hp=e5ff36f03452c5e94a0039a7e80b15c0fbe32005;hpb=74e99de094a34556ba912a5e392eda172571eb53;p=meshlink diff --git a/src/meshlink.c b/src/meshlink.c index e5ff36f0..33af6c36 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -21,6 +21,8 @@ #define VAR_MULTIPLE 4 /* Multiple statements allowed */ #define VAR_OBSOLETE 8 /* Should not be used anymore */ #define VAR_SAFE 16 /* Variable is safe when accepting invitations */ +#define MAX_ADDRESS_LENGTH 45 /* Max length of an (IPv6) address */ +#define MAX_PORT_LENGTH 5 /* 0-65535 */ typedef struct { const char *name; int type; @@ -39,6 +41,7 @@ typedef struct { #include "utils.h" #include "xalloc.h" #include "ed25519/sha512.h" +#include "discovery.h" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 @@ -740,7 +743,7 @@ static bool meshlink_setup(meshlink_handle_t *mesh) { return true; } -meshlink_handle_t *meshlink_open(const char *confbase, const char *name) { +meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const char* appname) { // Validate arguments provided by the application bool usingname = false; @@ -750,6 +753,12 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name) { return NULL; } + if(!appname || !*appname) { + fprintf(stderr, "No appname given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + if(!name || !*name) { fprintf(stderr, "No name given!\n"); //return NULL; @@ -765,6 +774,7 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name) { meshlink_handle_t *mesh = xzalloc(sizeof *mesh); mesh->confbase = xstrdup(confbase); + mesh->appname = xstrdup(appname); if (usingname) mesh->name = xstrdup(name); pthread_mutex_init ( &(mesh->outpacketqueue_mutex), NULL); pthread_mutex_init ( &(mesh->nodes_mutex), NULL); @@ -783,12 +793,15 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name) { if(access(filename, R_OK)) { if(errno == ENOENT) { // If not, create it - if(!meshlink_setup(mesh)) + if(!meshlink_setup(mesh)) { // meshlink_errno is set by meshlink_setup() return NULL; + } } else { fprintf(stderr, "Cannot not read from %s: %s\n", filename, strerror(errno)); - return meshlink_close(mesh), NULL; + meshlink_close(mesh); + meshlink_errno = MESHLINK_ESTORAGE; + return NULL; } } @@ -796,8 +809,11 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name) { init_configuration(&mesh->config); - if(!read_server_config(mesh)) - return meshlink_close(mesh), NULL; + if(!read_server_config(mesh)) { + meshlink_close(mesh); + meshlink_errno = MESHLINK_ESTORAGE; + return NULL; + }; #ifdef HAVE_MINGW struct WSAData wsa_state; @@ -807,8 +823,11 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name) { // Setup up everything // TODO: we should not open listening sockets yet - if(!setup_network(mesh)) - return meshlink_close(mesh), NULL; + if(!setup_network(mesh)) { + meshlink_close(mesh); + meshlink_errno = MESHLINK_ENETWORK; + return NULL; + } return mesh; } @@ -849,6 +868,10 @@ bool meshlink_start(meshlink_handle_t *mesh) { mesh->threadstarted=true; + // Start discovery + if(!discovery_start(mesh)) + return false; + return true; } @@ -858,6 +881,9 @@ void meshlink_stop(meshlink_handle_t *mesh) { return; } + // Stop discovery + discovery_stop(mesh); + // Shut down the listening sockets to signal the main thread to shut down for(int i = 0; i < mesh->listen_sockets; i++) { @@ -1004,6 +1030,27 @@ ssize_t meshlink_get_pmtu(meshlink_handle_t *mesh, meshlink_node_t *destination) return MTU; } +char *meshlink_get_fingerprint(meshlink_handle_t *mesh, meshlink_node_t *node) { + if(!mesh || !node) { + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + + node_t *n = (node_t *)node; + + if(!node_read_ecdsa_public_key(mesh, n) || !n->ecdsa) { + meshlink_errno = MESHLINK_EINTERNAL; + return false; + } + + char *fingerprint = ecdsa_get_base64_public_key(n->ecdsa); + + if(!fingerprint) + meshlink_errno = MESHLINK_EINTERNAL; + + return fingerprint; +} + meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) { if(!mesh || !name) { meshlink_errno = MESHLINK_EINVAL; @@ -1014,12 +1061,12 @@ meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) { } meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t *nmemb) { - if(!mesh || (nmemb && !nodes)) { + if(!mesh || !nmemb || (*nmemb && !nodes)) { meshlink_errno = MESHLINK_EINVAL; return NULL; } - meshlink_node_t **result, **p; + meshlink_node_t **result; //lock mesh->nodes pthread_mutex_lock(&(mesh->nodes_mutex)); @@ -1028,6 +1075,7 @@ meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_ result = realloc(nodes, *nmemb * sizeof *nodes); if(result) { + meshlink_node_t **p = result; for splay_each(node_t, n, mesh->nodes) *p++ = (meshlink_node_t *)n; } else { @@ -1616,6 +1664,47 @@ void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) { return; } +/* Hint that a hostname may be found at an address + * See header file for detailed comment. + */ +extern void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, struct sockaddr *addr) { + if(!mesh || !node || !addr) + return; + + char *addr_str = malloc(MAX_ADDRESS_LENGTH*sizeof(char)); + memset(addr_str, 0, MAX_ADDRESS_LENGTH*sizeof(char)); + + char *port_str = malloc(MAX_PORT_LENGTH*sizeof(char)); + memset(port_str, 0, MAX_PORT_LENGTH*sizeof(char)); + + // extra byte for a space, and one to make sure string is null-terminated + int full_addr_len = MAX_ADDRESS_LENGTH + MAX_PORT_LENGTH + 2; + + char *full_addr_str = malloc(full_addr_len*sizeof(char)); + memset(full_addr_str, 0, full_addr_len*sizeof(char)); + + // get address and port number + if(!get_ip_str(addr, addr_str, MAX_ADDRESS_LENGTH)) + goto fail; + if(!get_port_str(addr, port_str, MAX_ADDRESS_LENGTH)) + goto fail; + + // append_config_file expects an address, a space, and then a port number + strcat(full_addr_str, addr_str); + strcat(full_addr_str, " "); + strcat(full_addr_str, port_str); + + append_config_file(mesh, node->name, "Address", full_addr_str); + +fail: +done: + free(addr_str); + free(port_str); + free(full_addr_str); + + // @TODO do we want to fire off a connection attempt right away? +} + static void __attribute__((constructor)) meshlink_init(void) { crypto_init(); }