#include "xalloc.h"
#include "ed25519/sha512.h"
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
//TODO: this can go away completely
const var_t variables[] = {
}
}
- //if(!tty) {
- // if(!hostname) {
- // fprintf(stderr, "Could not determine the external address or hostname. Please set Address manually.\n");
- // return NULL;
- // }
- // goto save;
- //}
-
-again:
- fprintf(stderr, "Please enter your host's external address or hostname");
- if(hostname)
- fprintf(stderr, " [%s]", hostname);
- fprintf(stderr, ": ");
-
- if(!fgets(line, sizeof line, stdin)) {
- fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
- free(hostname);
+ if(!hostname)
return NULL;
- }
-
- if(!rstrip(line)) {
- if(hostname)
- goto save;
- else
- goto again;
- }
-
- for(char *p = line; *p; p++) {
- if(isalnum(*p) || *p == '-' || *p == '.')
- continue;
- fprintf(stderr, "Invalid address or hostname.\n");
- goto again;
- }
-
- free(hostname);
- hostname = xstrdup(line);
-save:
f = fopen(filename, "a");
if(f) {
fprintf(f, "\nAddress = %s\n", hostname);
FILE *fh = fopen(filename, "w");
if(!fh) {
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
+ fclose(f);
return false;
}
sptps_send_record(&(mesh->sptps), 1, b64key, strlen(b64key));
free(b64key);
+ free(mesh->self->name);
+ free(mesh->self->connection->name);
+ mesh->self->name = xstrdup(name);
+ mesh->self->connection->name = xstrdup(name);
+
fprintf(stderr, "Configuration stored in: %s\n", mesh->confbase);
+ load_all_nodes(mesh);
+
return true;
}
-static bool invitation_send(void *handle, uint8_t type, const char *data, size_t len) {
+static bool invitation_send(void *handle, uint8_t type, const void *data, size_t len) {
meshlink_handle_t* mesh = handle;
while(len) {
int result = send(mesh->sock, data, len, 0);
return true;
}
-static bool invitation_receive(void *handle, uint8_t type, const char *msg, uint16_t len) {
+static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint16_t len) {
meshlink_handle_t* mesh = handle;
switch(type) {
case SPTPS_HANDSHAKE:
if(!read_server_config(mesh))
return meshlink_close(mesh), NULL;
+#ifdef HAVE_MINGW
+ struct WSAData wsa_state;
+ WSAStartup(MAKEWORD(2, 2), &wsa_state);
+#endif
+
// Setup up everything
// TODO: we should not open listening sockets yet
}
void meshlink_stop(meshlink_handle_t *mesh) {
- // TODO: close the listening sockets to signal the main thread to shut down
+ // Shut down the listening sockets to signal the main thread to shut down
+
+ for(int i = 0; i < mesh->listen_sockets; i++) {
+ shutdown(mesh->listen_socket[i].tcp.fd, SHUT_RDWR);
+ shutdown(mesh->listen_socket[i].udp.fd, SHUT_RDWR);
+ }
// Wait for the main thread to finish
exit_configuration(&mesh->config);
event_loop_exit(&mesh->loop);
+
+#ifdef HAVE_MINGW
+ WSACleanup();
+#endif
}
void meshlink_set_receive_cb(meshlink_handle_t *mesh, meshlink_receive_cb_t cb) {
}
size_t meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t nmemb) {
- return 0;
+ size_t i = 0;
+
+ for splay_each(node_t, n, mesh->nodes) {
+ if(i < nmemb)
+ nodes[i] = (meshlink_node_t *)n;
+ i++;
+ }
+
+ return i;
}
char *meshlink_sign(meshlink_handle_t *mesh, const char *data, size_t len) {
snprintf(filename, sizeof filename, "%s" SLASH "invitations", mesh->confbase);
if(mkdir(filename, 0700) && errno != EEXIST) {
fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
- return NULL;
+ return false;
}
// Count the number of valid invitations, clean up old ones
DIR *dir = opendir(filename);
if(!dir) {
fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno));
- return NULL;
+ return false;
}
errno = 0;
if(!f) {
if(errno != ENOENT) {
fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno));
- return NULL;
+ return false;
}
mesh->invitation_key = ecdsa_generate();
if(!mesh->invitation_key) {
fprintf(stderr, "Could not generate a new key!\n");
- return NULL;
+ return false;
}
f = fopen(filename, "w");
if(!f) {
fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno));
- return NULL;
+ return false;
}
chmod(filename, 0600);
ecdsa_write_pem_private_key(mesh->invitation_key, f);
return mesh->invitation_key;
}
+bool meshlink_add_address(meshlink_handle_t *mesh, const char *address) {
+ for(const char *p = address; *p; p++) {
+ if(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')
+ continue;
+ fprintf(stderr, "Invalid character in address: %s\n", address);
+ return false;
+ }
+
+ return append_config_file(mesh, mesh->self->name, "Address", address);
+}
+
char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
// Check validity of the new node's name
if(!check_id(name)) {
return NULL;
}
+ // Get the local address
+ char *address = get_my_hostname(mesh);
+ if(!address) {
+ fprintf(stderr, "No Address known for ourselves!\n");
+ return NULL;
+ }
+
if(!refresh_invitation_key(mesh))
return NULL;
if(!f)
abort();
- // Get the local address
- char *address = get_my_hostname(mesh);
-
// Fill in the details.
fprintf(f, "Name = %s\n", name);
//if(netname)
}
char *meshlink_export(meshlink_handle_t *mesh) {
- return NULL;
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
+ FILE *f = fopen(filename, "r");
+ if(!f) {
+ fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
+ return NULL;
+ }
+
+ fseek(f, 0, SEEK_END);
+ int fsize = ftell(f);
+ rewind(f);
+
+ size_t len = fsize + 9 + strlen(mesh->self->name);
+ char *buf = xmalloc(len);
+ snprintf(buf, len, "Name = %s\n", mesh->self->name);
+ if(fread(buf + len - fsize - 1, fsize, 1, f) != 1) {
+ fprintf(stderr, "Error reading from %s: %s\n", filename, strerror(errno));
+ fclose(f);
+ return NULL;
+ }
+
+ fclose(f);
+ buf[len - 1] = 0;
+ return buf;
}
bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
- return false;
+ if(strncmp(data, "Name = ", 7)) {
+ fprintf(stderr, "Invalid data\n");
+ return false;
+ }
+
+ char *end = strchr(data + 7, '\n');
+ if(!end) {
+ fprintf(stderr, "Invalid data\n");
+ return false;
+ }
+
+ int len = end - (data + 7);
+ char name[len + 1];
+ memcpy(name, data + 7, len);
+ name[len] = 0;
+ if(!check_id(name)) {
+ fprintf(stderr, "Invalid Name\n");
+ return false;
+ }
+
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+ if(!access(filename, F_OK)) {
+ fprintf(stderr, "File %s already exists, not importing\n", filename);
+ return false;
+ }
+
+ if(errno != ENOENT) {
+ fprintf(stderr, "Error accessing %s: %s\n", filename, strerror(errno));
+ return false;
+ }
+
+ FILE *f = fopen(filename, "w");
+ if(!f) {
+ fprintf(stderr, "Could not create %s: %s\n", filename, strerror(errno));
+ return false;
+ }
+
+ fwrite(end + 1, strlen(end + 1), 1, f);
+ fclose(f);
+
+ load_all_nodes(mesh);
+
+ return true;
}
void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) {
+ node_t *n;
+ n = (node_t*)node;
+ n->status.blacklisted=true;
+ fprintf(stderr, "Blacklisted %s.\n",node->name);
+
+ //Make blacklisting persistent in the config file
+ append_config_file(mesh, n->name, "blacklisted", "yes");
+ return;
+
}
static void __attribute__((constructor)) meshlink_init(void) {