+ if(!ecdsa_keygen(mesh)) {
+ meshlink_errno = MESHLINK_EINTERNAL;
+ return false;
+ }
+
+ if(check_port(mesh) == 0) {
+ meshlink_errno = MESHLINK_ENETWORK;
+ return false;
+ }
+
+ /* Create a node for ourself */
+
+ mesh->self = new_node();
+ mesh->self->name = xstrdup(mesh->name);
+ 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)) {
+ 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)) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool meshlink_read_config(meshlink_handle_t *mesh) {
+ // Open the configuration file and lock it
+ 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)) {
+ logger(NULL, MESHLINK_ERROR, "Could not read main configuration file!");
+ return false;
+ }
+
+ packmsg_input_t in = {config.buf, config.len};
+ const void *private_key;
+ const void *invitation_key;
+
+ uint32_t version = packmsg_get_uint32(&in);
+ char *name = packmsg_get_str_dup(&in);
+ uint32_t private_key_len = packmsg_get_bin_raw(&in, &private_key);
+ uint32_t invitation_key_len = packmsg_get_bin_raw(&in, &invitation_key);
+ uint16_t myport = packmsg_get_uint16(&in);
+
+ if(!packmsg_done(&in) || version != MESHLINK_CONFIG_VERSION || private_key_len != 96 || invitation_key_len != 96) {
+ logger(NULL, MESHLINK_ERROR, "Error parsing main configuration file!");
+ free(name);
+ config_free(&config);
+ 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;
+ free(name);
+ config_free(&config);
+ return false;
+ }
+
+#endif
+
+ free(mesh->name);
+ mesh->name = name;
+ xasprintf(&mesh->myport, "%u", myport);
+ mesh->private_key = ecdsa_set_private_key(private_key);
+ mesh->invitation_key = ecdsa_set_private_key(invitation_key);
+ config_free(&config);
+
+ /* Create a node for ourself and read our host configuration file */
+
+ mesh->self = new_node();
+ mesh->self->name = xstrdup(name);
+ mesh->self->devclass = mesh->devclass;
+
+ if(!node_read_public_key(mesh, mesh->self)) {
+ logger(NULL, MESHLINK_ERROR, "Could not read our host configuration file!");
+ free_node(mesh->self);
+ mesh->self = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+#ifdef HAVE_SETNS
+static void *setup_network_in_netns_thread(void *arg) {
+ meshlink_handle_t *mesh = arg;
+
+ if(setns(mesh->netns, CLONE_NEWNET) != 0) {
+ return NULL;
+ }
+
+ bool success = setup_network(mesh);
+ add_local_addresses(mesh);
+ return success ? arg : NULL;
+}
+#endif // HAVE_SETNS
+
+meshlink_open_params_t *meshlink_open_params_init(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;
+ }
+
+ 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(!name || !*name) {
+ logger(NULL, MESHLINK_ERROR, "No name given!\n");
+ //return NULL;
+ } else { //check name only if there is a name != NULL
+ if(!check_id(name)) {
+ logger(NULL, MESHLINK_ERROR, "Invalid name given!\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+ }
+
+ if((int)devclass < 0 || devclass > _DEV_CLASS_MAX) {
+ logger(NULL, MESHLINK_ERROR, "Invalid devclass given!\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ meshlink_open_params_t *params = xzalloc(sizeof * params);
+
+ params->confbase = xstrdup(confbase);
+ params->name = xstrdup(name);
+ params->appname = xstrdup(appname);
+ params->devclass = devclass;
+ params->netns = -1;
+
+ return params;
+}
+
+bool meshlink_open_params_set_netns(meshlink_open_params_t *params, int netns) {
+ if(!params) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return false;
+ }
+
+ params->netns = netns;
+
+ return true;
+}
+
+bool meshlink_open_params_set_storage_key(meshlink_open_params_t *params, const void *key, size_t keylen) {
+ if(!params) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return false;
+ }
+
+ if((!key && keylen) || (key && !keylen)) {
+ logger(NULL, MESHLINK_ERROR, "Invalid key length!\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ return false;
+ }
+
+ params->key = key;
+ params->keylen = keylen;
+
+ return true;
+}