return 0;
}
+static bool write_main_config_files(meshlink_handle_t *mesh) {
+ if(!mesh->confbase) {
+ return true;
+ }
+
+ uint8_t buf[4096];
+
+ /* Write the main config file */
+ packmsg_output_t out = {buf, sizeof buf};
+
+ packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
+ packmsg_add_str(&out, mesh->name);
+ packmsg_add_bin(&out, ecdsa_get_private_key(mesh->private_key), 96);
+ packmsg_add_bin(&out, ecdsa_get_private_key(mesh->invitation_key), 96);
+ packmsg_add_uint16(&out, atoi(mesh->myport));
+
+ if(!packmsg_output_ok(&out)) {
+ return false;
+ }
+
+ config_t config = {buf, packmsg_output_size(&out, buf)};
+
+ if(!main_config_write(mesh, "current", &config, mesh->config_key)) {
+ return false;
+ }
+
+ /* Write our own host config file */
+ if(!node_write_config(mesh, mesh->self)) {
+ return false;
+ }
+
+ return true;
+}
+
static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len) {
packmsg_input_t in = {buf, len};
uint32_t version = packmsg_get_uint32(&in);
if(!check_id(name)) {
logger(mesh, MESHLINK_DEBUG, "Invalid Name found in invitation: %s!\n", name);
+ free(name);
return false;
}
if(!count) {
logger(mesh, MESHLINK_ERROR, "Incomplete invitation file!\n");
+ free(name);
return false;
}
- // Initialize configuration directory
- if(!config_init(mesh)) {
- return false;
- }
-
- // Write main config file
- uint8_t outbuf[4096];
- packmsg_output_t out = {outbuf, sizeof(outbuf)};
- packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
- packmsg_add_str(&out, name);
- packmsg_add_bin(&out, ecdsa_get_private_key(mesh->private_key), 96);
- packmsg_add_uint16(&out, atoi(mesh->myport));
-
- config_t config = {outbuf, packmsg_output_size(&out, outbuf)};
+ free(mesh->name);
+ free(mesh->self->name);
+ mesh->name = name;
+ mesh->self->name = xstrdup(name);
+ mesh->self->devclass = devclass;
- if(!main_config_write(mesh, &config)) {
+ // Initialize configuration directory
+ if(!config_init(mesh, "current")) {
return false;
}
- // Write our own host config file
- out.ptr = outbuf;
- out.len = sizeof(outbuf);
- packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
- packmsg_add_str(&out, name);
- packmsg_add_str(&out, CORE_MESH);
- packmsg_add_int32(&out, devclass);
- packmsg_add_bool(&out, false);
- packmsg_add_bin(&out, ecdsa_get_public_key(mesh->private_key), 32);
- packmsg_add_str(&out, ""); // TODO: copy existing canonical address, in case it was added before meshlink_join().
- packmsg_add_array(&out, 0);
-
- config.len = packmsg_output_size(&out, outbuf);
-
- if(!config_write(mesh, name, &config)) {
+ if(!write_main_config_files(mesh)) {
return false;
}
packmsg_input_t in2 = {data, len};
uint32_t version = packmsg_get_uint32(&in2);
+ char *name = packmsg_get_str_dup(&in2);
- if(version != MESHLINK_CONFIG_VERSION) {
- logger(mesh, MESHLINK_ERROR, "Invalid host config file in invitation file!\n");
- return false;
+ if(!packmsg_input_ok(&in2) || version != MESHLINK_CONFIG_VERSION || !check_id(name)) {
+ free(name);
+ packmsg_input_invalidate(&in);
+ break;
}
- char *host = packmsg_get_str_dup(&in2);
-
- if(!check_id(host)) {
- logger(mesh, MESHLINK_ERROR, "Invalid node name in invitation file!\n");
- free(host);
- return false;
+ if(!check_id(name)) {
+ free(name);
+ break;
}
- if(!strcmp(host, name)) {
+ if(!strcmp(name, mesh->name)) {
logger(mesh, MESHLINK_DEBUG, "Secondary chunk would overwrite our own host config file.\n");
- free(host);
+ free(name);
+ meshlink_errno = MESHLINK_EPEER;
return false;
}
+ node_t *n = new_node();
+ n->name = name;
+
config_t config = {data, len};
- config_write(mesh, host, &config);
- node_t *n = new_node();
- n->name = host;
- node_read_full(mesh, n);
- n->devclass = mesh->devclass;
+ if(!node_read_from_config(mesh, n, &config)) {
+ free_node(n);
+ logger(mesh, MESHLINK_ERROR, "Invalid host config file in invitation file!\n");
+ meshlink_errno = MESHLINK_EPEER;
+ return false;
+ }
+
node_add(mesh, n);
+
+ if(!config_write(mesh, "current", n->name, &config, mesh->config_key)) {
+ return false;
+ }
}
sptps_send_record(&(mesh->sptps), 1, ecdsa_get_public_key(mesh->private_key), 32);
- free(mesh->name);
- free(mesh->self->name);
- mesh->name = xstrdup(name);
- mesh->self->name = xstrdup(name);
-
logger(mesh, MESHLINK_DEBUG, "Configuration stored in: %s\n", mesh->confbase);
- load_all_nodes(mesh);
-
return true;
}
}
}
-#if 0
-static bool meshlink_write_config(meshlink_handle_t *mesh) {
- uint8_t buf[1024];
- packmsg_output_t out = {buf, sizeof buf};
- packmsg_add_str(&out, mesh->name);
- packmsg_add_uint32(&out, mesh->devclass);
- packmsg_add_uint16(&out, mesh->port);
- packmsg_add_bin(&out, ecdsa, sizeof(ecdsa));
- uint32_t len = packmsg_output_size(&out, buf);
-
- if(!len) {
- logger(mesh, MESHLINK_DEBUG, "Could not create configuration data\n",);
- meshlink_errno = MESHLINK_EINTERNAL;
- return false;
- }
-}
-#endif
-
static bool meshlink_setup(meshlink_handle_t *mesh) {
- if(!config_init(mesh)) {
- logger(mesh, MESHLINK_ERROR, "Could not set up configuration in %s: %s\n", mesh->confbase, strerror(errno));
+ if(!config_init(mesh, "current")) {
+ logger(mesh, MESHLINK_ERROR, "Could not set up configuration in %s/current: %s\n", mesh->confbase, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
return false;
}
mesh->self->devclass = mesh->devclass;
mesh->self->ecdsa = ecdsa_set_public_key(ecdsa_get_public_key(mesh->private_key));
- // Write the main config file
- uint8_t buf[4096];
- packmsg_output_t out = {buf, sizeof(buf)};
-
- packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
- packmsg_add_str(&out, mesh->name);
- packmsg_add_bin(&out, ecdsa_get_private_key(mesh->private_key), 96);
- packmsg_add_bin(&out, ecdsa_get_private_key(mesh->invitation_key), 96);
- packmsg_add_uint16(&out, atoi(mesh->myport));
-
- config_t config = {buf, packmsg_output_size(&out, buf)};
-
- if(!main_config_write(mesh, &config)) {
+ if(!write_main_config_files(mesh)) {
+ logger(mesh, MESHLINK_ERROR, "Could not write main config files into %s/current: %s\n", mesh->confbase, strerror(errno));
+ meshlink_errno = MESHLINK_ESTORAGE;
return false;
}
- // Write our own host config file
- out.ptr = buf;
- out.len = sizeof(buf);
- packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
- packmsg_add_str(&out, mesh->name);
- packmsg_add_int32(&out, mesh->devclass);
- packmsg_add_bool(&out, false);
- packmsg_add_bin(&out, ecdsa_get_public_key(mesh->private_key), 32);
- packmsg_add_str(&out, ""); // TODO: copy existing canonical address, in case it was added before meshlink_join().
- packmsg_add_array(&out, 0);
-
- config.len = packmsg_output_size(&out, buf);
-
- if(!config_write(mesh, mesh->name, &config)) {
+ if(!main_config_lock(mesh)) {
+ logger(NULL, MESHLINK_ERROR, "Cannot lock main config file\n");
+ meshlink_errno = MESHLINK_ESTORAGE;
return false;
}
config_t config;
- if(!main_config_read(mesh, &config)) {
+ if(!main_config_read(mesh, "current", &config, mesh->config_key)) {
logger(NULL, MESHLINK_ERROR, "Could not read main configuration file!");
return false;
}
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;
return false;
return true;
}
+bool meshlink_encrypted_key_rotate(meshlink_handle_t *mesh, const void *new_key, size_t new_keylen) {
+ if(!mesh || !new_key || !new_keylen) {
+ logger(mesh, MESHLINK_ERROR, "Invalid arguments given!\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ return false;
+ }
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
+ // Create hash for the new key
+ void *new_config_key;
+ new_config_key = xmalloc(CHACHA_POLY1305_KEYLEN);
+
+ if(!prf(new_key, new_keylen, "MeshLink configuration key", 26, new_config_key, CHACHA_POLY1305_KEYLEN)) {
+ logger(mesh, MESHLINK_ERROR, "Error creating new configuration key!\n");
+ meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return false;
+ }
+
+ // Copy contents of the "current" confbase sub-directory to "new" confbase sub-directory with the new key
+
+ if(!config_copy(mesh, "current", mesh->config_key, "new", new_config_key)) {
+ logger(mesh, MESHLINK_ERROR, "Could not set up configuration in %s/old: %s\n", mesh->confbase, strerror(errno));
+ meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return false;
+ }
+
+ devtool_keyrotate_probe(1);
+
+ main_config_unlock(mesh);
+
+ // Rename confbase/current/ to confbase/old
+
+ if(!config_rename(mesh, "current", "old")) {
+ logger(mesh, MESHLINK_ERROR, "Cannot rename %s/current to %s/old\n", mesh->confbase, mesh->confbase);
+ meshlink_errno = MESHLINK_ESTORAGE;
+ main_config_lock(mesh);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return false;
+ }
+
+ devtool_keyrotate_probe(2);
+
+ // Rename confbase/new/ to confbase/current
+
+ if(!config_rename(mesh, "new", "current")) {
+ logger(mesh, MESHLINK_ERROR, "Cannot rename %s/new to %s/current\n", mesh->confbase, mesh->confbase);
+ meshlink_errno = MESHLINK_ESTORAGE;
+ main_config_lock(mesh);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return false;
+ }
+
+ devtool_keyrotate_probe(3);
+
+ if(!main_config_lock(mesh)) {
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return false;
+ }
+
+ // Cleanup the "old" confbase sub-directory
+
+ if(!config_destroy(mesh->confbase, "old")) {
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return false;
+ }
+
+ // Change the mesh handle key with new key
+
+ free(mesh->config_key);
+ mesh->config_key = new_config_key;
+
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+
+ return true;
+}
+
void meshlink_open_params_free(meshlink_open_params_t *params) {
if(!params) {
meshlink_errno = MESHLINK_EINVAL;
}
meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const char *appname, dev_class_t devclass) {
+ if(!confbase || !*confbase) {
+ logger(NULL, MESHLINK_ERROR, "No confbase 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));
}
meshlink_handle_t *meshlink_open_encrypted(const char *confbase, const char *name, const char *appname, dev_class_t devclass, const void *key, size_t keylen) {
+ if(!confbase || !*confbase) {
+ logger(NULL, MESHLINK_ERROR, "No confbase 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 = {NULL};
return meshlink_open_ex(¶ms);
}
+meshlink_handle_t *meshlink_open_ephemeral(const char *name, const char *appname, dev_class_t devclass) {
+ /* Create a temporary struct on the stack, to avoid allocating and freeing one. */
+ meshlink_open_params_t params = {NULL};
+
+ params.name = (char *)name;
+ params.appname = (char *)appname;
+ params.devclass = devclass;
+ params.netns = -1;
+
+ return meshlink_open_ex(¶ms);
+}
+
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");
- if(!params->confbase || !*params->confbase) {
- logger(NULL, MESHLINK_ERROR, "No confbase given!\n");
- meshlink_errno = MESHLINK_EINVAL;
- return NULL;
- }
-
if(!params->appname || !*params->appname) {
logger(NULL, MESHLINK_ERROR, "No appname given!\n");
meshlink_errno = MESHLINK_EINVAL;
}
meshlink_handle_t *mesh = xzalloc(sizeof(meshlink_handle_t));
- mesh->confbase = xstrdup(params->confbase);
+
+ if(params->confbase) {
+ mesh->confbase = xstrdup(params->confbase);
+ }
+
mesh->appname = xstrdup(params->appname);
mesh->devclass = params->devclass;
mesh->discovery = true;
if(!prf(params->key, params->keylen, "MeshLink configuration key", 26, mesh->config_key, CHACHA_POLY1305_KEYLEN)) {
logger(NULL, MESHLINK_ERROR, "Error creating configuration key!\n");
+ meshlink_close(mesh);
meshlink_errno = MESHLINK_EINTERNAL;
return NULL;
}
// If no configuration exists yet, create it.
- if(!main_config_exists(mesh)) {
+ if(!meshlink_confbase_exists(mesh)) {
if(!meshlink_setup(mesh)) {
logger(NULL, MESHLINK_ERROR, "Cannot create initial configuration\n");
meshlink_close(mesh);
exit_outgoings(mesh);
+ // Write out any changed node config files
+ if(mesh->nodes) {
+ for splay_each(node_t, n, mesh->nodes) {
+ if(n->status.dirty) {
+ node_write_config(mesh, n);
+ n->status.dirty = false;
+ }
+ }
+ }
+
pthread_mutex_unlock(&(mesh->mesh_mutex));
}
void meshlink_close(meshlink_handle_t *mesh) {
- if(!mesh || !mesh->confbase) {
+ if(!mesh) {
meshlink_errno = MESHLINK_EINVAL;
return;
}
free(mesh->name);
free(mesh->appname);
free(mesh->confbase);
+ free(mesh->config_key);
+ ecdsa_free(mesh->private_key);
pthread_mutex_destroy(&(mesh->mesh_mutex));
main_config_unlock(mesh);
return false;
}
- return config_destroy(confbase);
+ if(!config_destroy(confbase, "current")) {
+ logger(NULL, MESHLINK_ERROR, "Cannot remove confbase sub-directories %s: %s\n", confbase, strerror(errno));
+ return false;
+ }
+
+ config_destroy(confbase, "new");
+ config_destroy(confbase, "old");
+
+ if(rmdir(confbase) && errno != ENOENT) {
+ logger(NULL, MESHLINK_ERROR, "Cannot remove directory %s: %s\n", confbase, strerror(errno));
+ meshlink_errno = MESHLINK_ESTORAGE;
+ return false;
+ }
+
+ return true;
}
void meshlink_set_receive_cb(meshlink_handle_t *mesh, meshlink_receive_cb_t cb) {
static bool search_node_by_dev_class(const node_t *node, const void *condition) {
dev_class_t *devclass = (dev_class_t *)condition;
- if(*devclass == node->devclass) {
+ if(*devclass == (dev_class_t)node->devclass) {
return true;
}
node_t *n = (node_t *)node;
free(n->canonical_address);
n->canonical_address = canonical_address;
- n->status.dirty = true;
+ node_write_config(mesh, n);
pthread_mutex_unlock(&(mesh->mesh_mutex));
goto done;
}
+ free(mesh->myport);
+ xasprintf(&mesh->myport, "%d", port);
+
+ /* Write meshlink.conf with the updated port number */
+ write_main_config_files(mesh);
+
+ /* Close down the network. This also deletes mesh->self. */
close_network_connections(mesh);
- // TODO: write meshlink.conf again
+ /* Recreate mesh->self. */
+ mesh->self = new_node();
+ mesh->self->name = xstrdup(mesh->name);
+ mesh->self->devclass = mesh->devclass;
+ xasprintf(&mesh->myport, "%d", port);
- if(!setup_network(mesh)) {
+ 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;
+ } else if(!setup_network(mesh)) {
meshlink_errno = MESHLINK_ENETWORK;
} else {
rval = true;
}
// Ensure no host configuration file with that name exists
- if(config_exists(mesh, name)) {
+ if(config_exists(mesh, "current", name)) {
logger(mesh, MESHLINK_DEBUG, "A host config file for %s already exists!\n", name);
meshlink_errno = MESHLINK_EEXIST;
pthread_mutex_unlock(&(mesh->mesh_mutex));
packmsg_add_str(&inv, s ? s->name : CORE_MESH);
packmsg_add_int32(&inv, DEV_CLASS_UNKNOWN); /* TODO: allow this to be set by inviter? */
- /* TODO: Add several host config files to bootstrap connections */
+ /* TODO: Add several host config files to bootstrap connections.
+ * Note: make sure we only add config files of nodes that are in the core mesh or the same submesh,
+ * and are not blacklisted.
+ */
config_t configs[5] = {NULL};
int count = 0;
- if(config_read(mesh, mesh->self->name, &configs[count])) {
+ if(config_read(mesh, "current", mesh->self->name, &configs[count], mesh->config_key)) {
count++;
}
config_t config = {outbuf, packmsg_output_size(&inv, outbuf)};
- if(!invitation_write(mesh, cookiehash, &config)) {
+ if(!invitation_write(mesh, "current", cookiehash, &config, mesh->config_key)) {
logger(mesh, MESHLINK_DEBUG, "Could not create invitation file %s: %s\n", cookiehash, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
pthread_mutex_unlock(&(mesh->mesh_mutex));
//Before doing meshlink_join make sure we are not connected to another mesh
if(mesh->threadstarted) {
- logger(mesh, MESHLINK_DEBUG, "Already connected to a mesh\n");
+ logger(mesh, MESHLINK_ERROR, "Cannot join while started\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return false;
+ }
+
+ // Refuse to join a mesh if we are already part of one. We are part of one if we know at least one other node.
+ if(mesh->nodes->count > 1) {
+ logger(mesh, MESHLINK_ERROR, "Already part of an existing mesh\n");
meshlink_errno = MESHLINK_EINVAL;
pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
mesh->blen = 0;
- if(!sendline(mesh->sock, "0 ?%s %d.%d %s", b64key, PROT_MAJOR, 1, mesh->appname)) {
+ if(!sendline(mesh->sock, "0 ?%s %d.%d %s", b64key, PROT_MAJOR, PROT_MINOR, mesh->appname)) {
logger(mesh, MESHLINK_DEBUG, "Error sending request to %s port %s: %s\n", address, port, strerror(errno));
closesocket(mesh->sock);
meshlink_errno = MESHLINK_ENETWORK;
return NULL;
}
- config_t config;
+ // Create a config file on the fly.
- // Get our config file
+ uint8_t buf[4096];
+ packmsg_output_t out = {buf, sizeof(buf)};
+ packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
+ packmsg_add_str(&out, mesh->name);
+ packmsg_add_str(&out, CORE_MESH);
pthread_mutex_lock(&(mesh->mesh_mutex));
- if(!config_read(mesh, mesh->self->name, &config)) {
- meshlink_errno = MESHLINK_ESTORAGE;
- pthread_mutex_unlock(&mesh->mesh_mutex);
- return NULL;
+ 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 : "");
+
+ uint32_t count = 0;
+
+ for(uint32_t i = 0; i < 5; i++) {
+ if(mesh->self->recent[i].sa.sa_family) {
+ count++;
+ } else {
+ break;
+ }
+ }
+
+ packmsg_add_array(&out, count);
+
+ for(uint32_t i = 0; i < count; i++) {
+ packmsg_add_sockaddr(&out, &mesh->self->recent[i]);
}
pthread_mutex_unlock(&(mesh->mesh_mutex));
+ if(!packmsg_output_ok(&out)) {
+ logger(mesh, MESHLINK_DEBUG, "Error creating export data\n");
+ meshlink_errno = MESHLINK_EINTERNAL;
+ return NULL;
+ }
+
// Prepare a base64-encoded packmsg array containing our config file
- uint8_t *buf = xmalloc(((config.len + 4) * 4) / 3 + 4);
- packmsg_output_t out = {buf, config.len + 4};
- packmsg_add_array(&out, 1);
- packmsg_add_bin(&out, config.buf, config.len);
- config_free(&config);
+ uint32_t len = packmsg_output_size(&out, buf);
+ uint32_t len2 = ((len + 4) * 4) / 3 + 4;
+ uint8_t *buf2 = xmalloc(len2);
+ packmsg_output_t out2 = {buf2, len2};
+ packmsg_add_array(&out2, 1);
+ packmsg_add_bin(&out2, buf, packmsg_output_size(&out, buf));
- if(!packmsg_output_ok(&out)) {
+ if(!packmsg_output_ok(&out2)) {
logger(mesh, MESHLINK_DEBUG, "Error creating export data\n");
meshlink_errno = MESHLINK_EINTERNAL;
- free(buf);
+ free(buf2);
return NULL;
}
- b64encode_urlsafe(buf, (char *)buf, packmsg_output_size(&out, buf));
+ b64encode_urlsafe(buf2, (char *)buf2, packmsg_output_size(&out2, buf2));
- return (char *)buf;
+ return (char *)buf2;
}
bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
if(!packmsg_input_ok(&in2) || version != MESHLINK_CONFIG_VERSION || !check_id(name)) {
free(name);
- packmsg_input_invalidate(&in2);
+ packmsg_input_invalidate(&in);
break;
}
node_t *n = lookup_node(mesh, name);
if(n) {
- free(name);
logger(mesh, MESHLINK_DEBUG, "Node %s already exists, not importing\n", name);
+ free(name);
continue;
}
n = new_node();
n->name = name;
- char *submesh_name = packmsg_get_str_dup(&in2);
-
- if(submesh_name) {
- if(!strcmp(submesh_name, CORE_MESH)) {
- n->submesh = NULL;
- } else {
- n->submesh = lookup_or_create_submesh(mesh, submesh_name);
- if(!n->submesh) {
- packmsg_input_invalidate(&in2);
- }
- }
-
- free(submesh_name);
- }
-
- n->devclass = packmsg_get_int32(&in2);
- n->status.blacklisted = packmsg_get_bool(&in2);
- const void *key;
- uint32_t keylen = packmsg_get_bin_raw(&in2, &key);
-
- if(keylen == 32) {
- n->ecdsa = ecdsa_set_public_key(key);
- }
-
- n->canonical_address = packmsg_get_str_dup(&in2);
- uint32_t count = packmsg_get_array(&in2);
-
- if(count > 5) {
- count = 5;
- }
-
- for(uint32_t i = 0; i < count; i++) {
- n->recent[i] = packmsg_get_sockaddr(&in2);
- }
+ config_t config = {data, len};
- if(!packmsg_done(&in2) || keylen != 32) {
- packmsg_input_invalidate(&in2);
+ if(!node_read_from_config(mesh, n, &config)) {
free_node(n);
- } else {
- config_t config = {data, len};
- config_write(mesh, n->name, &config);
- node_add(mesh, n);
+ packmsg_input_invalidate(&in);
+ break;
}
+
+ config_write(mesh, "current", n->name, &config, mesh->config_key);
+ node_add(mesh, n);
}
pthread_mutex_unlock(&(mesh->mesh_mutex));
}
n->status.blacklisted = true;
- n->status.dirty = true;
+ node_write_config(mesh, n);
logger(mesh, MESHLINK_DEBUG, "Blacklisted %s.\n", node->name);
//Immediately terminate any connections we have with the blacklisted node
}
n->status.blacklisted = false;
- n->status.dirty = true;
+ node_write_config(mesh, n);
pthread_mutex_unlock(&(mesh->mesh_mutex));
return;
node_t *n = (node_t *)node;
memmove(n->recent + 1, n->recent, 4 * sizeof(*n->recent));
memcpy(n->recent, addr, SALEN(*addr));
- n->status.dirty = true;
+ node_write_config(mesh, n);
pthread_mutex_unlock(&(mesh->mesh_mutex));
// @TODO do we want to fire off a connection attempt right away?