From b67296418c51784d39a24c3041e2cb199bee06f2 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 2 Oct 2017 22:58:49 +0200 Subject: [PATCH] Update astylerc and reformat the code. Changes: - Add braces to one-line if/else statements. - Add empty lines around control blocks. - Indent multi-line #defines with tabs. --- .astylerc | 4 +- Makefile.am | 3 + src/buffer.c | 6 +- src/conf.c | 133 ++++++++---- src/connection.c | 15 +- src/crypto.c | 11 +- src/devtools.c | 74 ++++--- src/discovery.c | 33 ++- src/dropin.c | 3 +- src/dropin.h | 26 +-- src/ed25519/ecdh.c | 2 +- src/ed25519/ecdsa.c | 17 +- src/ed25519/ecdsagen.c | 4 +- src/ed25519/ed25519.h | 16 +- src/edge.c | 16 +- src/event.c | 134 ++++++++---- src/fake-getaddrinfo.c | 15 +- src/fake-getnameinfo.c | 22 +- src/graph.c | 32 ++- src/hash.c | 29 ++- src/list.c | 55 +++-- src/logger.c | 14 +- src/meshlink++.h | 31 ++- src/meshlink.c | 471 +++++++++++++++++++++++++++++++---------- src/meshlink_queue.h | 18 +- src/meta.c | 30 ++- src/net.c | 135 ++++++++---- src/net_packet.c | 108 +++++++--- src/net_setup.c | 92 +++++--- src/net_socket.c | 147 +++++++++---- src/netutl.c | 43 ++-- src/node.c | 18 +- src/prf.c | 34 ++- src/protocol.c | 31 ++- src/protocol_auth.c | 93 ++++++-- src/protocol_edge.c | 10 +- src/protocol_key.c | 23 +- src/protocol_misc.c | 5 +- src/route.c | 18 +- src/splay_tree.c | 173 ++++++++++----- src/sptps.c | 223 +++++++++++++------ src/utcp | 2 +- src/utils.c | 41 +++- src/xalloc.h | 30 ++- 44 files changed, 1743 insertions(+), 697 deletions(-) diff --git a/.astylerc b/.astylerc index dd196454..ba38946c 100644 --- a/.astylerc +++ b/.astylerc @@ -1,8 +1,10 @@ --indent=tab=8 --convert-tabs --xj +-j +-f -A2 -U -p -xg -k3 +-w diff --git a/Makefile.am b/Makefile.am index 3bf6bdee..42146893 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,3 +10,6 @@ EXTRA_DIST = README.android ChangeLog: git log > ChangeLog + +astyle: + astyle --options=.astylerc -nQ src/*.[ch] src/ed25519/e*.[ch] diff --git a/src/buffer.c b/src/buffer.c index ccef7279..cc35918d 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -82,8 +82,9 @@ static char *buffer_consume(buffer_t *buffer, size_t size) { char *buffer_readline(buffer_t *buffer) { char *newline = memchr(buffer->data + buffer->offset, '\n', buffer->len - buffer->offset); - if(!newline) + if(!newline) { return NULL; + } size_t len = newline + 1 - (buffer->data + buffer->offset); *newline = 0; @@ -93,8 +94,9 @@ char *buffer_readline(buffer_t *buffer) { // Check if we have enough bytes in the buffer, and if so, return a pointer to the start of them. char *buffer_read(buffer_t *buffer, size_t size) { - if(buffer->len - buffer->offset < size) + if(buffer->len - buffer->offset < size) { return NULL; + } return buffer_consume(buffer, size); } diff --git a/src/conf.c b/src/conf.c index 8bfa855d..fcaefdd2 100644 --- a/src/conf.c +++ b/src/conf.c @@ -36,15 +36,17 @@ static int config_compare(const config_t *a, const config_t *b) { result = strcasecmp(a->variable, b->variable); - if(result) + if(result) { return result; + } result = a->line - b->line; - if(result) + if(result) { return result; - else + } else { return a->file ? strcmp(a->file, b->file) : 0; + } } void init_configuration(splay_tree_t **config_tree) { @@ -52,8 +54,10 @@ void init_configuration(splay_tree_t **config_tree) { } void exit_configuration(splay_tree_t **config_tree) { - if(*config_tree) + if(*config_tree) { splay_delete_tree(*config_tree); + } + *config_tree = NULL; } @@ -62,14 +66,17 @@ config_t *new_config(void) { } void free_config(config_t *cfg) { - if(cfg->variable) + if(cfg->variable) { free(cfg->variable); + } - if(cfg->value) + if(cfg->value) { free(cfg->value); + } - if(cfg->file) + if(cfg->file) { free(cfg->file); + } free(cfg); } @@ -87,11 +94,13 @@ config_t *lookup_config(splay_tree_t *config_tree, char *variable) { found = splay_search_closest_greater(config_tree, &cfg); - if(!found) + if(!found) { return NULL; + } - if(strcasecmp(found->variable, variable)) + if(strcasecmp(found->variable, variable)) { return NULL; + } return found; } @@ -106,8 +115,9 @@ config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *cfg) { if(node->next) { found = node->next->data; - if(!strcasecmp(found->variable, cfg->variable)) + if(!strcasecmp(found->variable, cfg->variable)) { return found; + } } } @@ -115,8 +125,9 @@ config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *cfg) { } bool get_config_bool(const config_t *cfg, bool *result) { - if(!cfg) + if(!cfg) { return false; + } if(!strcasecmp(cfg->value, "yes")) { *result = true; @@ -133,11 +144,13 @@ bool get_config_bool(const config_t *cfg, bool *result) { } bool get_config_int(const config_t *cfg, int *result) { - if(!cfg) + if(!cfg) { return false; + } - if(sscanf(cfg->value, "%d", result) == 1) + if(sscanf(cfg->value, "%d", result) == 1) { return true; + } logger(NULL, MESHLINK_ERROR, "Integer expected for configuration variable %s in %s line %d", cfg->variable, cfg->file, cfg->line); @@ -146,14 +159,16 @@ bool get_config_int(const config_t *cfg, int *result) { } bool set_config_int(config_t *cfg, int val) { - if(!cfg) + if(!cfg) { return false; + } char val_str[1024]; snprintf(val_str, sizeof(val_str), "%d", val); - if(cfg->value) + if(cfg->value) { free(cfg->value); + } cfg->value = xstrdup(val_str); @@ -161,8 +176,9 @@ bool set_config_int(config_t *cfg, int val) { } bool get_config_string(const config_t *cfg, char **result) { - if(!cfg) + if(!cfg) { return false; + } *result = xstrdup(cfg->value); @@ -170,11 +186,13 @@ bool get_config_string(const config_t *cfg, char **result) { } bool set_config_string(config_t *cfg, const char *val) { - if(!cfg) + if(!cfg) { return false; + } - if(cfg->value) + if(cfg->value) { free(cfg->value); + } cfg->value = xstrdup(val); @@ -184,8 +202,9 @@ bool set_config_string(config_t *cfg, const char *val) { bool get_config_address(const config_t *cfg, struct addrinfo **result) { struct addrinfo *ai; - if(!cfg) + if(!cfg) { return false; + } ai = str2addrinfo(cfg->value, NULL, 0); @@ -207,23 +226,28 @@ static char *readline(FILE *fp, char *buf, size_t buflen) { char *newline = NULL; char *p; - if(feof(fp)) + if(feof(fp)) { return NULL; + } p = fgets(buf, buflen, fp); - if(!p) + if(!p) { return NULL; + } newline = strchr(p, '\n'); - if(!newline) + if(!newline) { return buf; + } /* kill newline and carriage return if necessary */ *newline = '\0'; - if(newline > p && newline[-1] == '\r') + + if(newline > p && newline[-1] == '\r') { newline[-1] = '\0'; + } return buf; } @@ -235,16 +259,20 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) { variable = value = line; eol = line + strlen(line); - while(strchr("\t ", *--eol)) + + while(strchr("\t ", *--eol)) { *eol = '\0'; + } len = strcspn(value, "\t ="); value += len; value += strspn(value, "\t "); + if(*value == '=') { value++; value += strspn(value, "\t "); } + variable[len] = '\0'; if(!*value) { @@ -287,19 +315,24 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) { line = readline(fp, buffer, sizeof(buffer)); if(!line) { - if(feof(fp)) + if(feof(fp)) { result = true; + } + break; } lineno++; - if(!*line || *line == '#') + if(!*line || *line == '#') { continue; + } if(ignore) { - if(!strncmp(line, "-----END", 8)) + if(!strncmp(line, "-----END", 8)) { ignore = false; + } + continue; } @@ -309,8 +342,11 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) { } cfg = parse_config_line(line, fname, lineno); - if(!cfg) + + if(!cfg) { break; + } + config_add(config_tree, cfg); } @@ -330,17 +366,21 @@ bool write_config_file(const struct splay_tree_t *config_tree, const char *fname } for splay_each(config_t, cnf, config_tree) { - if(fwrite(cnf->variable, sizeof(char), strlen(cnf->variable), fp) < strlen(cnf->variable)) + if(fwrite(cnf->variable, sizeof(char), strlen(cnf->variable), fp) < strlen(cnf->variable)) { goto error; + } - if(fwrite(" = ", sizeof(char), 3, fp) < 3) + if(fwrite(" = ", sizeof(char), 3, fp) < 3) { goto error; + } - if(fwrite(cnf->value, sizeof(char), strlen(cnf->value), fp) < strlen(cnf->value)) + if(fwrite(cnf->value, sizeof(char), strlen(cnf->value), fp) < strlen(cnf->value)) { goto error; + } - if(fwrite("\n", sizeof(char), 1, fp) < 1) + if(fwrite("\n", sizeof(char), 1, fp) < 1) { goto error; + } } fclose(fp); @@ -360,8 +400,9 @@ bool read_server_config(meshlink_handle_t *mesh) { errno = 0; x = read_config_file(mesh->config, filename); - if(!x && errno) + if(!x && errno) { logger(mesh, MESHLINK_ERROR, "Failed to read `%s': %s", filename, strerror(errno)); + } return x; } @@ -418,27 +459,34 @@ bool modify_config_file(struct meshlink_handle *mesh, const char *name, const ch } while(readline(fr, buf, sizeof(buf))) { - if(!*buf || *buf == '#') + if(!*buf || *buf == '#') { goto copy; + } sep = strchr(buf, ' '); - if(!sep) + + if(!sep) { goto copy; + } *sep = 0; + if(strcmp(buf, key)) { *sep = ' '; goto copy; } // We found the key and the value. We already added it at the top, so ignore this one. - if(value && sep[1] == '=' && sep[2] == ' ' && !strcmp(sep + 3, value)) + if(value && sep[1] == '=' && sep[2] == ' ' && !strcmp(sep + 3, value)) { continue; + } // We found the key but with a different value, delete it if wanted. found++; - if((!value || trim) && found > trim) + + if((!value || trim) && found > trim) { continue; + } *sep = ' '; @@ -446,16 +494,19 @@ copy: fprintf(fw, "%s\n", buf); } - if(ferror(fr)) + if(ferror(fr)) { error = true; + } fclose(fr); - if(ferror(fw)) + if(ferror(fw)) { error = true; + } - if(fclose(fw)) + if(fclose(fw)) { error = true; + } // If any error occured during reading or writing, exit. if(error) { @@ -467,9 +518,11 @@ copy: #ifdef HAVE_MINGW char bakname[PATH_MAX]; snprintf(bakname, sizeof(bakname), "%s.bak", filename); + if(rename(filename, bakname) || rename(tmpname, filename)) { rename(bakname, filename); #else + if(rename(tmpname, filename)) { #endif return false; diff --git a/src/connection.c b/src/connection.c index dc4dad2d..9b80db6b 100644 --- a/src/connection.c +++ b/src/connection.c @@ -35,8 +35,9 @@ void init_connections(meshlink_handle_t *mesh) { } void exit_connections(meshlink_handle_t *mesh) { - if(mesh->connections) + if(mesh->connections) { list_delete_list(mesh->connections); + } free_connection(mesh->everyone); @@ -49,8 +50,9 @@ connection_t *new_connection(void) { } void free_connection(connection_t *c) { - if(!c) + if(!c) { return; + } sptps_stop(&c->sptps); ecdsa_free(c->ecdsa); @@ -58,16 +60,19 @@ void free_connection(connection_t *c) { buffer_clear(&c->inbuf); buffer_clear(&c->outbuf); - if(c->io.cb) + if(c->io.cb) { abort(); + } - if(c->socket > 0) + if(c->socket > 0) { closesocket(c->socket); + } free(c->name); - if(c->config_tree) + if(c->config_tree) { exit_configuration(&c->config_tree); + } free(c); } diff --git a/src/crypto.c b/src/crypto.c index e3797f8d..b5309b0f 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -29,8 +29,11 @@ static int random_fd = -1; void crypto_init(void) { random_fd = open("/dev/urandom", O_RDONLY); - if(random_fd < 0) + + if(random_fd < 0) { random_fd = open("/dev/random", O_RDONLY); + } + if(random_fd < 0) { fprintf(stderr, "Could not open source of random numbers: %s\n", strerror(errno)); abort(); @@ -44,12 +47,16 @@ void crypto_exit(void) { void randomize(void *out, size_t outlen) { while(outlen) { size_t len = read(random_fd, out, outlen); + if(len <= 0) { - if(errno == EAGAIN || errno == EINTR) + if(errno == EAGAIN || errno == EINTR) { continue; + } + fprintf(stderr, "Could not read random numbers: %s\n", strerror(errno)); abort(); } + out += len; outlen -= len; } diff --git a/src/devtools.c b/src/devtools.c index a8fc56b8..d4c00f13 100644 --- a/src/devtools.c +++ b/src/devtools.c @@ -47,10 +47,11 @@ devtool_edge_t *devtool_get_all_edges(meshlink_handle_t *mesh, devtool_edge_t *e result_size = mesh->edges->count / 2; // if result is smaller than edges, we have to dealloc all the excess devtool_edge_t - if((size_t)result_size > *nmemb) + if((size_t)result_size > *nmemb) { result = realloc(edges, result_size * sizeof(*result)); - else + } else { result = edges; + } if(result) { devtool_edge_t *p = result; @@ -58,12 +59,14 @@ devtool_edge_t *devtool_get_all_edges(meshlink_handle_t *mesh, devtool_edge_t *e for splay_each(edge_t, e, mesh->edges) { // skip edges that do not represent a two-directional connection - if((!e->reverse) || (e->reverse->to != e->from)) + if((!e->reverse) || (e->reverse->to != e->from)) { continue; + } // don't count edges twice - if(e->to < e->from) + if(e->to < e->from) { continue; + } assert(n < result_size); @@ -93,8 +96,9 @@ devtool_edge_t *devtool_get_all_edges(meshlink_handle_t *mesh, devtool_edge_t *e static bool fstrwrite(const char *str, FILE *stream) { size_t len = strlen(str); - if(fwrite((void *)str, 1, len, stream) != len) + if(fwrite((void *)str, 1, len, stream) != len) { return false; + } return true; } @@ -102,8 +106,9 @@ static bool fstrwrite(const char *str, FILE *stream) { static const char *__itoa(int value) { static char buffer[sizeof(int) * 8 + 1]; // not thread safe - if(snprintf(buffer, sizeof(buffer), "%d", value) == -1) + if(snprintf(buffer, sizeof(buffer), "%d", value) == -1) { return ""; + } return buffer; } @@ -120,57 +125,71 @@ bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream) meshlink_node_t **nodes = meshlink_get_all_nodes(mesh, NULL, &node_count); devtool_edge_t *edges = devtool_get_all_edges(mesh, NULL, &edge_count); - if((!nodes && node_count != 0) || (!edges && edge_count != 0)) + if((!nodes && node_count != 0) || (!edges && edge_count != 0)) { goto fail; + } // export begin - if(!fstrwrite("{\n", stream)) + if(!fstrwrite("{\n", stream)) { goto fail; + } // export nodes - if(!fstrwrite("\t\"nodes\": {\n", stream)) + if(!fstrwrite("\t\"nodes\": {\n", stream)) { goto fail; + } for(size_t i = 0; i < node_count; ++i) { - if(!fstrwrite("\t\t\"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\": {\n", stream)) + if(!fstrwrite("\t\t\"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\": {\n", stream)) { goto fail; + } - if(!fstrwrite("\t\t\t\"name\": \"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\",\n", stream)) + if(!fstrwrite("\t\t\t\"name\": \"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\",\n", stream)) { goto fail; + } - if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->options), stream) || !fstrwrite(",\n", stream)) + if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->options), stream) || !fstrwrite(",\n", stream)) { goto fail; + } - if(!fstrwrite("\t\t\t\"devclass\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->devclass), stream) || !fstrwrite("\n", stream)) + if(!fstrwrite("\t\t\t\"devclass\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->devclass), stream) || !fstrwrite("\n", stream)) { goto fail; + } - if(!fstrwrite((i + 1) != node_count ? "\t\t},\n" : "\t\t}\n", stream)) + if(!fstrwrite((i + 1) != node_count ? "\t\t},\n" : "\t\t}\n", stream)) { goto fail; + } } - if(!fstrwrite("\t},\n", stream)) + if(!fstrwrite("\t},\n", stream)) { goto fail; + } // export edges - if(!fstrwrite("\t\"edges\": {\n", stream)) + if(!fstrwrite("\t\"edges\": {\n", stream)) { goto fail; + } for(size_t i = 0; i < edge_count; ++i) { - if(!fstrwrite("\t\t\"", stream) || !fstrwrite(edges[i].from->name, stream) || !fstrwrite("_to_", stream) || !fstrwrite(edges[i].to->name, stream) || !fstrwrite("\": {\n", stream)) + if(!fstrwrite("\t\t\"", stream) || !fstrwrite(edges[i].from->name, stream) || !fstrwrite("_to_", stream) || !fstrwrite(edges[i].to->name, stream) || !fstrwrite("\": {\n", stream)) { goto fail; + } - if(!fstrwrite("\t\t\t\"from\": \"", stream) || !fstrwrite(edges[i].from->name, stream) || !fstrwrite("\",\n", stream)) + if(!fstrwrite("\t\t\t\"from\": \"", stream) || !fstrwrite(edges[i].from->name, stream) || !fstrwrite("\",\n", stream)) { goto fail; + } - if(!fstrwrite("\t\t\t\"to\": \"", stream) || !fstrwrite(edges[i].to->name, stream) || !fstrwrite("\",\n", stream)) + if(!fstrwrite("\t\t\t\"to\": \"", stream) || !fstrwrite(edges[i].to->name, stream) || !fstrwrite("\",\n", stream)) { goto fail; + } char *host = NULL, *port = NULL, *address = NULL; sockaddr2str((const sockaddr_t *) & (edges[i].address), &host, &port); - if(host && port) + if(host && port) { xasprintf(&address, "{ \"host\": \"%s\", \"port\": %s }", host, port); + } free(host); free(port); @@ -182,23 +201,28 @@ bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream) free(address); - if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(edges[i].options), stream) || !fstrwrite(",\n", stream)) + if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(edges[i].options), stream) || !fstrwrite(",\n", stream)) { goto fail; + } - if(!fstrwrite("\t\t\t\"weight\": ", stream) || !fstrwrite(__itoa(edges[i].weight), stream) || !fstrwrite("\n", stream)) + if(!fstrwrite("\t\t\t\"weight\": ", stream) || !fstrwrite(__itoa(edges[i].weight), stream) || !fstrwrite("\n", stream)) { goto fail; + } - if(!fstrwrite((i + 1) != edge_count ? "\t\t},\n" : "\t\t}\n", stream)) + if(!fstrwrite((i + 1) != edge_count ? "\t\t},\n" : "\t\t}\n", stream)) { goto fail; + } } - if(!fstrwrite("\t}\n", stream)) + if(!fstrwrite("\t}\n", stream)) { goto fail; + } // DONE! - if(!fstrwrite("}", stream)) + if(!fstrwrite("}", stream)) { goto fail; + } goto done; diff --git a/src/discovery.c b/src/discovery.c index 5b83862d..c74c71c2 100644 --- a/src/discovery.c +++ b/src/discovery.c @@ -21,8 +21,9 @@ #define MESHLINK_MDNS_FINGERPRINT_KEY "fingerprint" static void generate_rand_string(char *buffer, size_t size) { - for(size_t i = 0; i < (size - 1); ++i) + for(size_t i = 0; i < (size - 1); ++i) { buffer[i] = 'a' + (rand() % ('z' - 'a' + 1)); + } buffer[size - 1] = '\0'; } @@ -106,6 +107,7 @@ static void discovery_create_services(meshlink_handle_t *mesh) { /* Add the service */ int ret = 0; + if((ret = catta_server_add_service(mesh->catta_server, mesh->catta_group, CATTA_IF_UNSPEC, CATTA_PROTO_UNSPEC, 0, meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self), mesh->catta_servicetype, NULL, NULL, atoi(mesh->myport), txt_name, txt_fingerprint, NULL)) < 0) { logger(mesh, MESHLINK_ERROR, "Failed to add service: %s\n", catta_strerror(ret)); goto fail; @@ -123,8 +125,10 @@ fail: catta_simple_poll_quit(mesh->catta_poll); done: - if(txt_name) + + if(txt_name) { free(txt_name); + } pthread_mutex_unlock(&(mesh->mesh_mutex)); } @@ -142,8 +146,9 @@ static void discovery_server_callback(CattaServer *server, CattaServerState stat case CATTA_SERVER_RUNNING: { /* The serve has startup successfully and registered its host * name on the network, so it's time to create our services */ - if(!mesh->catta_group) + if(!mesh->catta_group) { discovery_create_services(mesh); + } } break; @@ -291,16 +296,20 @@ static void discovery_resolve_callback(CattaSServiceResolver *resolver, CattaIfI break; } - if(naddress.unknown.family != AF_UNKNOWN) + if(naddress.unknown.family != AF_UNKNOWN) { meshlink_hint_address(mesh, (meshlink_node_t *)node, (struct sockaddr *)&naddress); - else + } else { logger(mesh, MESHLINK_WARNING, "Could not resolve node %s to a known address family type.\n", node->name); - } else + } + } else { logger(mesh, MESHLINK_WARNING, "Node %s is not part of the mesh network.\n", node_name); - } else + } + } else { logger(mesh, MESHLINK_WARNING, "TXT records invalid.\n"); - } else + } + } else { logger(mesh, MESHLINK_WARNING, "TXT records missing.\n"); + } } break; } @@ -337,12 +346,14 @@ static void discovery_browse_callback(CattaSServiceBrowser *browser, CattaIfInde assert(domain != NULL); logger(mesh, MESHLINK_DEBUG, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); + /* We ignore the returned resolver object. In the callback function we free it. Ifthe server is terminated before the callback function is called the server will free the resolver for us. */ - if(!(catta_s_service_resolver_new(mesh->catta_server, interface_, protocol, name, type, domain, CATTA_PROTO_UNSPEC, 0, discovery_resolve_callback, mesh))) + if(!(catta_s_service_resolver_new(mesh->catta_server, interface_, protocol, name, type, domain, CATTA_PROTO_UNSPEC, 0, discovery_resolve_callback, mesh))) { logger(mesh, MESHLINK_DEBUG, "Failed to resolve service '%s': %s\n", name, catta_strerror(catta_server_errno(mesh->catta_server))); + } } break; @@ -480,6 +491,7 @@ bool discovery_start(meshlink_handle_t *mesh) { return true; fail: + if(mesh->catta_browser != NULL) { catta_s_service_browser_free(mesh->catta_browser); mesh->catta_browser = NULL; @@ -510,8 +522,9 @@ void discovery_stop(meshlink_handle_t *mesh) { assert(mesh != NULL); // Shut down - if(mesh->catta_poll) + if(mesh->catta_poll) { catta_simple_poll_quit(mesh->catta_poll); + } // Wait for the discovery thread to finish if(mesh->discovery_threadstarted == true) { diff --git a/src/dropin.c b/src/dropin.c index 1cd06fc1..9fbd6b9e 100644 --- a/src/dropin.c +++ b/src/dropin.c @@ -77,8 +77,9 @@ int vasprintf(char **buf, const char *fmt, va_list ap) { status = vsnprintf(*buf, len, fmt, aq); va_end(aq); - if(status >= 0) + if(status >= 0) { *buf = xrealloc(*buf, status + 1); + } if(status > len - 1) { len = status; diff --git a/src/dropin.h b/src/dropin.h index 06db98b0..a85f8110 100644 --- a/src/dropin.h +++ b/src/dropin.h @@ -41,21 +41,23 @@ extern int usleep(long long usec); #endif #ifndef timeradd -#define timeradd(a, b, r) do {\ - (r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\ - (r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\ - if((r)->tv_usec >= 1000000)\ - (r)->tv_sec++, (r)->tv_usec -= 1000000;\ -} while (0) +#define timeradd(a, b, r)\ + do {\ + (r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\ + (r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\ + if((r)->tv_usec >= 1000000)\ + (r)->tv_sec++, (r)->tv_usec -= 1000000;\ + } while (0) #endif #ifndef timersub -#define timersub(a, b, r) do {\ - (r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\ - (r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\ - if((r)->tv_usec < 0)\ - (r)->tv_sec--, (r)->tv_usec += 1000000;\ -} while (0) +#define timersub(a, b, r)\ + do {\ + (r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\ + (r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\ + if((r)->tv_usec < 0)\ + (r)->tv_sec--, (r)->tv_usec += 1000000;\ + } while (0) #endif #ifdef HAVE_MINGW diff --git a/src/ed25519/ecdh.c b/src/ed25519/ecdh.c index 94ebab60..844b0fcc 100644 --- a/src/ed25519/ecdh.c +++ b/src/ed25519/ecdh.c @@ -31,7 +31,7 @@ typedef struct ecdh_t { #include "../xalloc.h" ecdh_t *ecdh_generate_public(void *pubkey) { - ecdh_t *ecdh = xzalloc(sizeof *ecdh); + ecdh_t *ecdh = xzalloc(sizeof * ecdh); uint8_t seed[32]; randomize(seed, sizeof seed); diff --git a/src/ed25519/ecdsa.c b/src/ed25519/ecdsa.c index 2606a21e..ec53c070 100644 --- a/src/ed25519/ecdsa.c +++ b/src/ed25519/ecdsa.c @@ -42,8 +42,9 @@ ecdsa_t *ecdsa_set_base64_public_key(const char *p) { return 0; } - ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa); + ecdsa_t *ecdsa = xzalloc(sizeof * ecdsa); len = b64decode(p, ecdsa->public, len); + if(len != 32) { logger(NULL, MESHLINK_ERROR, "Invalid format of public key! len = %d", len); free(ecdsa); @@ -63,17 +64,23 @@ char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) { // Read PEM ECDSA keys ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) { - ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa); - if(fread(ecdsa->public, sizeof ecdsa->public, 1, fp) == 1) + ecdsa_t *ecdsa = xzalloc(sizeof * ecdsa); + + if(fread(ecdsa->public, sizeof ecdsa->public, 1, fp) == 1) { return ecdsa; + } + free(ecdsa); return 0; } ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) { - ecdsa_t *ecdsa = xmalloc(sizeof *ecdsa); - if(fread(ecdsa, sizeof *ecdsa, 1, fp) == 1) + ecdsa_t *ecdsa = xmalloc(sizeof * ecdsa); + + if(fread(ecdsa, sizeof * ecdsa, 1, fp) == 1) { return ecdsa; + } + free(ecdsa); return 0; } diff --git a/src/ed25519/ecdsagen.c b/src/ed25519/ecdsagen.c index 4414259e..4238bf53 100644 --- a/src/ed25519/ecdsagen.c +++ b/src/ed25519/ecdsagen.c @@ -36,7 +36,7 @@ typedef struct { // Generate ECDSA key ecdsa_t *ecdsa_generate(void) { - ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa); + ecdsa_t *ecdsa = xzalloc(sizeof * ecdsa); uint8_t seed[32]; randomize(seed, sizeof seed); @@ -52,5 +52,5 @@ bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) { } bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) { - return fwrite(ecdsa, sizeof *ecdsa, 1, fp) == 1; + return fwrite(ecdsa, sizeof * ecdsa, 1, fp) == 1; } diff --git a/src/ed25519/ed25519.h b/src/ed25519/ed25519.h index bb34f893..0e6e57c6 100644 --- a/src/ed25519/ed25519.h +++ b/src/ed25519/ed25519.h @@ -4,15 +4,15 @@ #include #if defined(_WIN32) - #if defined(ED25519_BUILD_DLL) - #define ED25519_DECLSPEC __declspec(dllexport) - #elif defined(ED25519_DLL) - #define ED25519_DECLSPEC __declspec(dllimport) - #else - #define ED25519_DECLSPEC - #endif +#if defined(ED25519_BUILD_DLL) +#define ED25519_DECLSPEC __declspec(dllexport) +#elif defined(ED25519_DLL) +#define ED25519_DECLSPEC __declspec(dllimport) #else - #define ED25519_DECLSPEC +#define ED25519_DECLSPEC +#endif +#else +#define ED25519_DECLSPEC #endif diff --git a/src/edge.c b/src/edge.c index efb90dfe..f3d21d93 100644 --- a/src/edge.c +++ b/src/edge.c @@ -37,13 +37,15 @@ static int edge_weight_compare(const edge_t *a, const edge_t *b) { result = a->weight - b->weight; - if(result) + if(result) { return result; + } result = strcmp(a->from->name, b->from->name); - if(result) + if(result) { return result; + } return strcmp(a->to->name, b->to->name); } @@ -61,8 +63,10 @@ void free_edge_tree(splay_tree_t *edge_tree) { } void exit_edges(meshlink_handle_t *mesh) { - if(mesh->edges) + if(mesh->edges) { splay_delete_tree(mesh->edges); + } + mesh->edges = NULL; } @@ -84,13 +88,15 @@ void edge_add(meshlink_handle_t *mesh, edge_t *e) { e->reverse = lookup_edge(e->to, e->from); - if(e->reverse) + if(e->reverse) { e->reverse->reverse = e; + } } void edge_del(meshlink_handle_t *mesh, edge_t *e) { - if(e->reverse) + if(e->reverse) { e->reverse->reverse = NULL; + } splay_delete(mesh->edges, e); splay_delete(e->from->edge_tree, e); diff --git a/src/event.c b/src/event.c index 54d69658..3978c30b 100644 --- a/src/event.c +++ b/src/event.c @@ -33,24 +33,38 @@ static int io_compare(const io_t *a, const io_t *b) { static int timeout_compare(const timeout_t *a, const timeout_t *b) { struct timeval diff; timersub(&a->tv, &b->tv, &diff); - if(diff.tv_sec < 0) + + if(diff.tv_sec < 0) { return -1; - if(diff.tv_sec > 0) + } + + if(diff.tv_sec > 0) { return 1; - if(diff.tv_usec < 0) + } + + if(diff.tv_usec < 0) { return -1; - if(diff.tv_usec > 0) + } + + if(diff.tv_usec > 0) { return 1; - if(a < b) + } + + if(a < b) { return -1; - if(a > b) + } + + if(a > b) { return 1; + } + return 0; } void io_add(event_loop_t *loop, io_t *io, io_cb_t cb, void *data, int fd, int flags) { - if(io->cb) + if(io->cb) { return; + } io->fd = fd; io->cb = cb; @@ -59,27 +73,31 @@ void io_add(event_loop_t *loop, io_t *io, io_cb_t cb, void *data, int fd, int fl io_set(loop, io, flags); - if(!splay_insert_node(&loop->ios, &io->node)) + if(!splay_insert_node(&loop->ios, &io->node)) { abort(); + } } void io_set(event_loop_t *loop, io_t *io, int flags) { io->flags = flags; - if(flags & IO_READ) + if(flags & IO_READ) { FD_SET(io->fd, &loop->readfds); - else + } else { FD_CLR(io->fd, &loop->readfds); + } - if(flags & IO_WRITE) + if(flags & IO_WRITE) { FD_SET(io->fd, &loop->writefds); - else + } else { FD_CLR(io->fd, &loop->writefds); + } } void io_del(event_loop_t *loop, io_t *io) { - if(!io->cb) + if(!io->cb) { return; + } loop->deletion = true; @@ -96,28 +114,34 @@ void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void * }; timeout->cb = cb; + timeout->data = data; + timeout->node.data = timeout; timeout_set(loop, timeout, tv); } void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timeval *tv) { - if(timerisset(&timeout->tv)) + if(timerisset(&timeout->tv)) { splay_unlink_node(&loop->timeouts, &timeout->node); + } - if(!loop->now.tv_sec) + if(!loop->now.tv_sec) { gettimeofday(&loop->now, NULL); + } timeradd(&loop->now, tv, &timeout->tv); - if(!splay_insert_node(&loop->timeouts, &timeout->node)) + if(!splay_insert_node(&loop->timeouts, &timeout->node)) { abort(); + } } void timeout_del(event_loop_t *loop, timeout_t *timeout) { - if(!timeout->cb) + if(!timeout->cb) { return; + } loop->deletion = true; @@ -136,19 +160,24 @@ static void signalio_handler(event_loop_t *loop, void *data, int flags) { (void)data; (void)flags; unsigned char signum; - if(read(loop->pipefd[0], &signum, 1) != 1) + + if(read(loop->pipefd[0], &signum, 1) != 1) { return; + } signal_t *sig = splay_search(&loop->signals, &((signal_t) { .signum = signum })); - if(sig) + + if(sig) { sig->cb(loop, sig->data); + } } static void pipe_init(event_loop_t *loop) { - if(!pipe(loop->pipefd)) + if(!pipe(loop->pipefd)) { io_add(loop, &loop->signalio, signalio_handler, NULL, loop->pipefd[0], IO_READ); + } } void signal_trigger(event_loop_t *loop, signal_t *sig) { @@ -160,24 +189,28 @@ void signal_trigger(event_loop_t *loop, signal_t *sig) { } void signal_add(event_loop_t *loop, signal_t *sig, signal_cb_t cb, void *data, uint8_t signum) { - if(sig->cb) + if(sig->cb) { return; + } sig->cb = cb; sig->data = data; sig->signum = signum; sig->node.data = sig; - if(loop->pipefd[0] == -1) + if(loop->pipefd[0] == -1) { pipe_init(loop); + } - if(!splay_insert_node(&loop->signals, &sig->node)) + if(!splay_insert_node(&loop->signals, &sig->node)) { abort(); + } } void signal_del(event_loop_t *loop, signal_t *sig) { - if(!sig->cb) + if(!sig->cb) { return; + } loop->deletion = true; @@ -204,8 +237,10 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { if(diff.tv_sec < 0) { timeout->cb(loop, timeout->data); - if(timercmp(&timeout->tv, &loop->now, <)) + + if(timercmp(&timeout->tv, &loop->now, <)) { timeout_del(loop, timeout); + } } else { tv = &diff; break; @@ -214,8 +249,10 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { if(loop->idle_cb) { it = loop->idle_cb(loop, loop->idle_data); - if(it.tv_sec >= 0 && (!tv || timercmp(&it, tv, <))) + + if(it.tv_sec >= 0 && (!tv || timercmp(&it, tv, <))) { tv = ⁢ + } } memcpy(&readable, &loop->readfds, sizeof(readable)); @@ -229,21 +266,27 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { } // release mesh mutex during select - if(mutex) + if(mutex) { pthread_mutex_unlock(mutex); + } + int n = select(fds, &readable, &writable, NULL, tv); - if(mutex) + + if(mutex) { pthread_mutex_lock(mutex); + } if(n < 0) { - if(sockwouldblock(errno)) + if(sockwouldblock(errno)) { continue; - else + } else { return false; + } } - if(!n) + if(!n) { continue; + } // Normally, splay_each allows the current node to be deleted. However, // it can be that one io callback triggers the deletion of another io, @@ -252,14 +295,21 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { loop->deletion = false; for splay_each(io_t, io, &loop->ios) { - if(FD_ISSET(io->fd, &writable) && io->cb) + if(FD_ISSET(io->fd, &writable) && io->cb) { io->cb(loop, io->data, IO_WRITE); - if(loop->deletion) + } + + if(loop->deletion) { break; - if(FD_ISSET(io->fd, &readable) && io->cb) + } + + if(FD_ISSET(io->fd, &readable) && io->cb) { io->cb(loop, io->data, IO_READ); - if(loop->deletion) + } + + if(loop->deletion) { break; + } } } @@ -268,8 +318,9 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { void event_flush_output(event_loop_t *loop) { for splay_each(io_t, io, &loop->ios) - if(FD_ISSET(io->fd, &loop->writefds)) + if(FD_ISSET(io->fd, &loop->writefds)) { io->cb(loop, io->data, IO_WRITE); + } } void event_loop_start(event_loop_t *loop) { @@ -290,10 +341,15 @@ void event_loop_init(event_loop_t *loop) { } void event_loop_exit(event_loop_t *loop) { - for splay_each(io_t, io, &loop->ios) + for splay_each(io_t, io, &loop->ios) { splay_unlink_node(&loop->ios, node); - for splay_each(timeout_t, timeout, &loop->timeouts) + } + + for splay_each(timeout_t, timeout, &loop->timeouts) { splay_unlink_node(&loop->timeouts, node); - for splay_each(signal_t, signal, &loop->signals) + } + + for splay_each(signal_t, signal, &loop->signals) { splay_unlink_node(&loop->signals, node); + } } diff --git a/src/fake-getaddrinfo.c b/src/fake-getaddrinfo.c index 37a65b89..9aaddaf8 100644 --- a/src/fake-getaddrinfo.c +++ b/src/fake-getaddrinfo.c @@ -20,10 +20,13 @@ char *gai_strerror(int ecode) { switch(ecode) { case EAI_NODATA: return "No address associated with hostname"; + case EAI_MEMORY: return "Memory allocation failure"; + case EAI_FAMILY: return "Address family not supported"; + default: return "Unknown error"; } @@ -65,11 +68,13 @@ int getaddrinfo(const char *hostname, const char *servname, const struct addrinf int i; uint16_t port = 0; - if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) + if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) { return EAI_FAMILY; + } - if(servname) + if(servname) { port = htons(atoi(servname)); + } if(hints && hints->ai_flags & AI_PASSIVE) { *res = malloc_ai(port, htonl(0x00000000)); @@ -83,14 +88,16 @@ int getaddrinfo(const char *hostname, const char *servname, const struct addrinf hp = gethostbyname(hostname); - if(!hp || !hp->h_addr_list || !hp->h_addr_list[0]) + if(!hp || !hp->h_addr_list || !hp->h_addr_list[0]) { return EAI_NODATA; + } for(i = 0; hp->h_addr_list[i]; i++) { *res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr); - if(prev) + if(prev) { prev->ai_next = *res; + } prev = *res; } diff --git a/src/fake-getnameinfo.c b/src/fake-getnameinfo.c index 4a4d1328..88b78a59 100644 --- a/src/fake-getnameinfo.c +++ b/src/fake-getnameinfo.c @@ -21,33 +21,43 @@ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t host struct hostent *hp; int len; - if(sa->sa_family != AF_INET) + if(sa->sa_family != AF_INET) { return EAI_FAMILY; + } if(serv && servlen) { len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port)); - if(len < 0 || len >= servlen) + + if(len < 0 || len >= servlen) { return EAI_MEMORY; + } } - if(!host || !hostlen) + if(!host || !hostlen) { return 0; + } if(flags & NI_NUMERICHOST) { len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr)); - if(len < 0 || len >= hostlen) + + if(len < 0 || len >= hostlen) { return EAI_MEMORY; + } + return 0; } hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET); - if(!hp || !hp->h_name || !hp->h_name[0]) + if(!hp || !hp->h_name || !hp->h_name[0]) { return EAI_NODATA; + } len = snprintf(host, hostlen, "%s", hp->h_name); - if(len < 0 || len >= hostlen) + + if(len < 0 || len >= hostlen) { return EAI_MEMORY; + } return 0; } diff --git a/src/graph.c b/src/graph.c index 2b76194f..a6e38e42 100644 --- a/src/graph.c +++ b/src/graph.c @@ -64,15 +64,17 @@ static void mst_kruskal(meshlink_handle_t *mesh) { /* Clear MST status on connections */ - for list_each(connection_t, c, mesh->connections) + for list_each(connection_t, c, mesh->connections) { c->status.mst = false; + } logger(mesh, MESHLINK_DEBUG, "Running Kruskal's algorithm:"); /* Clear visited status on nodes */ - for splay_each(node_t, n, mesh->nodes) + for splay_each(node_t, n, mesh->nodes) { n->status.visited = false; + } /* Starting point */ @@ -96,11 +98,13 @@ static void mst_kruskal(meshlink_handle_t *mesh) { e->from->status.visited = true; e->to->status.visited = true; - if(e->connection) + if(e->connection) { e->connection->status.mst = true; + } - if(e->reverse->connection) + if(e->reverse->connection) { e->reverse->connection->status.mst = true; + } logger(mesh, MESHLINK_DEBUG, " Adding edge %s - %s weight %d", e->from->name, e->to->name, e->weight); @@ -141,12 +145,14 @@ static void sssp_bfs(meshlink_handle_t *mesh) { for list_each(node_t, n, todo_list) { /* "n" is the node from which we start */ logger(mesh, MESHLINK_DEBUG, " Examining edges from %s", n->name); - if(n->distance < 0) + if(n->distance < 0) { abort(); + } for splay_each(edge_t, e, n->edge_tree) { /* "e" is the edge connected to "from" */ - if(!e->reverse) + if(!e->reverse) { continue; + } /* Situation: @@ -169,8 +175,9 @@ static void sssp_bfs(meshlink_handle_t *mesh) { if(e->to->status.visited && (!e->to->status.indirect || indirect) - && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) + && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) { continue; + } e->to->status.visited = true; e->to->status.indirect = indirect; @@ -180,8 +187,9 @@ static void sssp_bfs(meshlink_handle_t *mesh) { e->to->options = e->options; e->to->distance = n->distance + 1; - if(!e->to->status.reachable || (e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN)) + if(!e->to->status.reachable || (e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN)) { update_node_udp(mesh, e->to, &e->address); + } list_insert_tail(todo_list, e->to); } @@ -201,10 +209,11 @@ static void check_reachability(meshlink_handle_t *mesh) { n->status.reachable = !n->status.reachable; n->last_state_change = mesh->loop.now.tv_sec; - if(n->status.reachable) + if(n->status.reachable) { logger(mesh, MESHLINK_DEBUG, "Node %s became reachable", n->name); - else + } else { logger(mesh, MESHLINK_DEBUG, "Node %s became unreachable", n->name); + } /* TODO: only clear status.validkey if node is unreachable? */ @@ -227,8 +236,9 @@ static void check_reachability(meshlink_handle_t *mesh) { memset(&n->status, 0, sizeof(n)->status); n->options = 0; } else if(n->connection) { - if(n->connection->outgoing) + if(n->connection->outgoing) { send_req_key(mesh, n); + } } } } diff --git a/src/hash.c b/src/hash.c index 5d90e55c..a7964428 100644 --- a/src/hash.c +++ b/src/hash.c @@ -27,26 +27,34 @@ static uint32_t hash_function(const void *p, size_t len) { const uint8_t *q = p; uint32_t hash = 0; + while(true) { - for(int i = len > 4 ? 4 : len; --i;) + for(int i = len > 4 ? 4 : len; --i;) { hash += q[len - i] << (8 * i); + } + hash *= 0x9e370001UL; // Golden ratio prime. - if(len <= 4) + + if(len <= 4) { break; + } + len -= 4; } + return hash; } /* Map 32 bits int onto 0..n-1, without throwing away too many bits if n is 2^8 or 2^16 */ static uint32_t modulo(uint32_t hash, size_t n) { - if(n == 0x100) + if(n == 0x100) { return (hash >> 24) ^ ((hash >> 16) & 0xff) ^ ((hash >> 8) & 0xff) ^ (hash & 0xff); - else if(n == 0x10000) + } else if(n == 0x10000) { return (hash >> 16) ^ (hash & 0xffff); - else + } else { return hash % n; + } } /* (De)allocation */ @@ -76,15 +84,21 @@ void hash_insert(hash_t *hash, const void *key, const void *value) { void *hash_search(const hash_t *hash, const void *key) { uint32_t i = modulo(hash_function(key, hash->size), hash->n); - if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) + + if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) { return (void *)hash->values[i]; + } + return NULL; } void *hash_search_or_insert(hash_t *hash, const void *key, const void *value) { uint32_t i = modulo(hash_function(key, hash->size), hash->n); - if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) + + if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) { return (void *)hash->values[i]; + } + memcpy(hash->keys + i * hash->size, key, hash->size); hash->values[i] = value; return NULL; @@ -99,6 +113,7 @@ void hash_clear(hash_t *hash) { void hash_resize(hash_t *hash, size_t n) { hash->keys = xrealloc(hash->keys, n * hash->size); hash->values = xrealloc(hash->values, n * sizeof(*hash->values)); + if(n > hash->n) { memset(hash->keys + hash->n * hash->size, 0, (n - hash->n) * hash->size); memset(hash->values + hash->n, 0, (n - hash->n) * sizeof(*hash->values)); diff --git a/src/list.c b/src/list.c index c74eb213..c75cf146 100644 --- a/src/list.c +++ b/src/list.c @@ -40,8 +40,9 @@ list_node_t *list_alloc_node(void) { } void list_free_node(list_t *list, list_node_t *node) { - if(node->data && list->delete) + if(node->data && list->delete) { list->delete(node->data); + } free(node); } @@ -56,10 +57,11 @@ list_node_t *list_insert_head(list_t *list, void *data) { node->next = list->head; list->head = node; - if(node->next) + if(node->next) { node->next->prev = node; - else + } else { list->tail = node; + } list->count++; @@ -74,10 +76,11 @@ list_node_t *list_insert_tail(list_t *list, void *data) { node->prev = list->tail; list->tail = node; - if(node->prev) + if(node->prev) { node->prev->next = node; - else + } else { list->head = node; + } list->count++; @@ -92,10 +95,11 @@ list_node_t *list_insert_after(list_t *list, list_node_t *after, void *data) { node->prev = after; after->next = node; - if(node->next) + if(node->next) { node->next->prev = node; - else + } else { list->tail = node; + } list->count++; @@ -112,10 +116,11 @@ list_node_t *list_insert_before(list_t *list, list_node_t *before, void *data) { node->prev = before->prev; before->prev = node; - if(node->prev) + if(node->prev) { node->prev->next = node; - else + } else { list->head = node; + } list->count++; @@ -123,15 +128,17 @@ list_node_t *list_insert_before(list_t *list, list_node_t *before, void *data) { } void list_unlink_node(list_t *list, list_node_t *node) { - if(node->prev) + if(node->prev) { node->prev->next = node->next; - else + } else { list->head = node->next; + } - if(node->next) + if(node->next) { node->next->prev = node->prev; - else + } else { list->tail = node->prev; + } list->count--; } @@ -151,31 +158,35 @@ void list_delete_tail(list_t *list) { void list_delete(list_t *list, const void *data) { for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) - if(node->data == data) + if(node->data == data) { list_delete_node(list, node); + } } /* Head/tail lookup */ void *list_get_head(list_t *list) { - if(list->head) + if(list->head) { return list->head->data; - else + } else { return NULL; + } } void *list_get_tail(list_t *list) { - if(list->tail) + if(list->tail) { return list->tail->data; - else + } else { return NULL; + } } /* Fast list deletion */ void list_delete_list(list_t *list) { - for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) + for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) { list_free_node(list, node); + } list_free(list); } @@ -183,12 +194,14 @@ void list_delete_list(list_t *list) { /* Traversing */ void list_foreach_node(list_t *list, list_action_node_t action) { - for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) + for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) { action(node); + } } void list_foreach(list_t *list, list_action_t action) { for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) - if(node->data) + if(node->data) { action(node->data); + } } diff --git a/src/logger.c b/src/logger.c index 97fddecd..48c9564c 100644 --- a/src/logger.c +++ b/src/logger.c @@ -26,11 +26,13 @@ // TODO: refactor logging code to use a meshlink_handle_t *. void logger(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *format, ...) { if(mesh) { - if(level < mesh->log_level || !mesh->log_cb) + if(level < mesh->log_level || !mesh->log_cb) { return; + } } else { - if(level < global_log_level || !global_log_cb) + if(level < global_log_level || !global_log_cb) { return; + } } va_list ap; @@ -40,11 +42,13 @@ void logger(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *for int len = vsnprintf(message, sizeof(message), format, ap); va_end(ap); - if(len > 0 && (size_t)len < sizeof(message) && message[len - 1] == '\n') + if(len > 0 && (size_t)len < sizeof(message) && message[len - 1] == '\n') { message[len - 1] = 0; + } - if(mesh) + if(mesh) { mesh->log_cb(mesh, level, message); - else + } else { global_log_cb(NULL, level, message); + } } diff --git a/src/meshlink++.h b/src/meshlink++.h index bfc7173d..6a384166 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -139,8 +139,10 @@ public: */ bool open(const char *confbase, const char *name, const char *appname, dev_class_t devclass) { handle = meshlink_open(confbase, name, appname, devclass); - if(handle) + + if(handle) { handle->priv = this; + } return isOpen(); } @@ -159,6 +161,7 @@ public: handle->priv = 0; meshlink_close(handle); } + handle = 0; } @@ -575,48 +578,62 @@ private: /// static callback trampolines: static void receive_trampoline(meshlink_handle_t *handle, meshlink_node_t *source, const void *data, size_t length) { - if(!(handle->priv)) + if(!(handle->priv)) { return; + } + meshlink::mesh *that = static_cast(handle->priv); that->receive(static_cast(source), data, length); } static void node_status_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer, bool reachable) { - if(!(handle->priv)) + if(!(handle->priv)) { return; + } + meshlink::mesh *that = static_cast(handle->priv); that->node_status(static_cast(peer), reachable); } static void log_trampoline(meshlink_handle_t *handle, log_level_t level, const char *message) { - if(!(handle->priv)) + if(!(handle->priv)) { return; + } + meshlink::mesh *that = static_cast(handle->priv); that->log(level, message); } static bool channel_accept_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, uint16_t port, const void *data, size_t len) { - if(!(handle->priv)) + if(!(handle->priv)) { return false; + } + meshlink::mesh *that = static_cast(handle->priv); bool accepted = that->channel_accept(static_cast(channel), port, data, len); + if(accepted) { meshlink_set_channel_receive_cb(handle, channel, &channel_receive_trampoline); meshlink_set_channel_poll_cb(handle, channel, &channel_poll_trampoline); } + return accepted; } static void channel_receive_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, const void *data, size_t len) { - if(!(handle->priv)) + if(!(handle->priv)) { return; + } + meshlink::mesh *that = static_cast(handle->priv); that->channel_receive(static_cast(channel), data, len); } static void channel_poll_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, size_t len) { - if(!(handle->priv)) + if(!(handle->priv)) { return; + } + meshlink::mesh *that = static_cast(handle->priv); that->channel_poll(static_cast(channel), len); } diff --git a/src/meshlink.c b/src/meshlink.c index 094d4983..d4a5b2a4 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -119,6 +119,7 @@ const var_t variables[] = { static bool fcopy(FILE *out, const char *filename) { FILE *in = fopen(filename, "r"); + if(!in) { logger(NULL, MESHLINK_ERROR, "Could not open %s: %s\n", filename, strerror(errno)); return false; @@ -126,57 +127,80 @@ static bool fcopy(FILE *out, const char *filename) { char buf[1024]; size_t len; - while((len = fread(buf, 1, sizeof(buf), in))) + + while((len = fread(buf, 1, sizeof(buf), in))) { fwrite(buf, len, 1, out); + } + fclose(in); return true; } static int rstrip(char *value) { int len = strlen(value); - while(len && strchr("\t\r\n ", value[len - 1])) + + while(len && strchr("\t\r\n ", value[len - 1])) { value[--len] = 0; + } + return len; } static void scan_for_hostname(const char *filename, char **hostname, char **port) { char line[4096]; - if(!filename || (*hostname && *port)) + + if(!filename || (*hostname && *port)) { return; + } FILE *f = fopen(filename, "r"); - if(!f) + + if(!f) { return; + } while(fgets(line, sizeof(line), f)) { - if(!rstrip(line)) + if(!rstrip(line)) { continue; + } + char *p = line, *q; p += strcspn(p, "\t ="); - if(!*p) + + if(!*p) { continue; + } + q = p + strspn(p, "\t "); - if(*q == '=') + + if(*q == '=') { q += 1 + strspn(q + 1, "\t "); + } + *p = 0; p = q + strcspn(q, "\t "); - if(*p) + + if(*p) { *p++ = 0; + } + p += strspn(p, "\t "); p[strcspn(p, "\t ")] = 0; - if(!*port && !strcasecmp(line, "Port")) + if(!*port && !strcasecmp(line, "Port")) { *port = xstrdup(q); - else if(!*hostname && !strcasecmp(line, "Address")) { + } else if(!*hostname && !strcasecmp(line, "Address")) { *hostname = xstrdup(q); + if(*p) { free(*port); *port = xstrdup(p); } } - if(*hostname && *port) + if(*hostname && *port) { break; + } } fclose(f); @@ -184,8 +208,9 @@ static void scan_for_hostname(const char *filename, char **hostname, char **port static bool is_valid_hostname(const char *hostname) { for(const char *p = hostname; *p; p++) { - if(!(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')) + if(!(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')) { return false; + } } return true; @@ -214,34 +239,48 @@ char *meshlink_get_external_address(meshlink_handle_t *mesh) { while(aip) { int s = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol); + if(s >= 0) { set_timeout(s, 5000); + if(connect(s, aip->ai_addr, aip->ai_addrlen)) { closesocket(s); s = -1; } } + if(s >= 0) { send(s, request, sizeof(request) - 1, 0); int len = recv(s, line, sizeof(line) - 1, MSG_WAITALL); + if(len > 0) { line[len] = 0; - if(line[len - 1] == '\n') + + if(line[len - 1] == '\n') { line[--len] = 0; + } + char *p = strrchr(line, '\n'); - if(p && p[1]) + + if(p && p[1]) { hostname = xstrdup(p + 1); + } } + closesocket(s); - if(hostname) + + if(hostname) { break; + } } + aip = aip->ai_next; continue; } - if(ai) + if(ai) { freeaddrinfo(ai); + } // Check that the hostname is reasonable if(hostname && !is_valid_hostname(hostname)) { @@ -249,8 +288,9 @@ char *meshlink_get_external_address(meshlink_handle_t *mesh) { hostname = NULL; } - if(!hostname) + if(!hostname) { meshlink_errno = MESHLINK_ERESOLV; + } return hostname; } @@ -267,31 +307,39 @@ static char *get_my_hostname(meshlink_handle_t *mesh) { snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name); scan_for_hostname(filename, &hostname, &port); - if(hostname) + if(hostname) { goto done; + } hostname = meshlink_get_external_address(mesh); - if(!hostname) + + if(!hostname) { return NULL; + } f = fopen(filename, "a"); + if(f) { fprintf(f, "\nAddress = %s\n", hostname); fclose(f); - } else + } else { logger(mesh, MESHLINK_DEBUG, "Could not append Address to %s: %s\n", filename, strerror(errno)); + } done: + if(port) { - if(strchr(hostname, ':')) + if(strchr(hostname, ':')) { xasprintf(&hostport, "[%s]:%s", hostname, port); - else + } else { xasprintf(&hostport, "%s:%s", hostname, port); + } } else { - if(strchr(hostname, ':')) + if(strchr(hostname, ':')) { xasprintf(&hostport, "[%s]", hostname); - else + } else { hostport = xstrdup(hostname); + } } free(hostname); @@ -300,8 +348,9 @@ done: } static char *get_line(const char **data) { - if(!data || !*data) + if(!data || !*data) { return NULL; + } if(! **data) { *data = NULL; @@ -311,36 +360,48 @@ static char *get_line(const char **data) { static char line[1024]; const char *end = strchr(*data, '\n'); size_t len = end ? (size_t)(end - *data) : strlen(*data); + if(len >= sizeof(line)) { logger(NULL, MESHLINK_ERROR, "Maximum line length exceeded!\n"); return NULL; } - if(len && !isprint(**data)) + + if(len && !isprint(**data)) { abort(); + } memcpy(line, *data, len); line[len] = 0; - if(end) + if(end) { *data = end + 1; - else + } else { *data = NULL; + } return line; } static char *get_value(const char *data, const char *var) { char *line = get_line(&data); - if(!line) + + if(!line) { return NULL; + } char *sep = line + strcspn(line, " \t="); char *val = sep + strspn(sep, " \t"); - if(*val == '=') + + if(*val == '=') { val += 1 + strspn(val + 1, " \t"); + } + *sep = 0; - if(strcasecmp(line, var)) + + if(strcasecmp(line, var)) { return NULL; + } + return val; } @@ -356,21 +417,26 @@ static bool try_bind(int port) { char portstr[16]; snprintf(portstr, sizeof(portstr), "%d", port); - if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) + if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) { return false; + } while(ai) { int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); + if(!fd) { freeaddrinfo(ai); return false; } + int result = bind(fd, ai->ai_addr, ai->ai_addrlen); closesocket(fd); + if(result) { freeaddrinfo(ai); return false; } + ai = ai->ai_next; } @@ -381,10 +447,12 @@ static bool try_bind(int port) { static int check_port(meshlink_handle_t *mesh) { for(int i = 0; i < 1000; i++) { int port = 0x1000 + (rand() & 0x7fff); + if(try_bind(port)) { char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->name); FILE *f = fopen(filename, "a"); + if(!f) { logger(mesh, MESHLINK_DEBUG, "Please change MeshLink's Port manually.\n"); return 0; @@ -402,6 +470,7 @@ static int check_port(meshlink_handle_t *mesh) { static bool finalize_join(meshlink_handle_t *mesh) { char *name = xstrdup(get_value(mesh->data, "Name")); + if(!name) { logger(mesh, MESHLINK_DEBUG, "No Name found in invitation!\n"); return false; @@ -416,6 +485,7 @@ static bool finalize_join(meshlink_handle_t *mesh) { snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", mesh->confbase); FILE *f = fopen(filename, "w"); + if(!f) { logger(mesh, MESHLINK_DEBUG, "Could not create file %s: %s\n", filename, strerror(errno)); return false; @@ -425,6 +495,7 @@ static bool finalize_join(meshlink_handle_t *mesh) { snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name); FILE *fh = fopen(filename, "w"); + if(!fh) { logger(mesh, MESHLINK_DEBUG, "Could not create file %s: %s\n", filename, strerror(errno)); fclose(f); @@ -438,34 +509,41 @@ static bool finalize_join(meshlink_handle_t *mesh) { while((l = get_line(&p))) { // Ignore comments - if(*l == '#') + if(*l == '#') { continue; + } // Split line into variable and value int len = strcspn(l, "\t ="); value = l + len; value += strspn(value, "\t "); + if(*value == '=') { value++; value += strspn(value, "\t "); } + l[len] = 0; // Is it a Name? if(!strcasecmp(l, "Name")) - if(strcmp(value, name)) + if(strcmp(value, name)) { break; - else + } else { continue; - else if(!strcasecmp(l, "NetName")) + } else if(!strcasecmp(l, "NetName")) { continue; + } // Check the list of known variables //TODO: most variables will not be available in meshlink, only name and key will be absolutely necessary bool found = false; int i; + for(i = 0; variables[i].name; i++) { - if(strcasecmp(l, variables[i].name)) + if(strcasecmp(l, variables[i].name)) { continue; + } + found = true; break; } @@ -505,16 +583,21 @@ static bool finalize_join(meshlink_handle_t *mesh) { } while((l = get_line(&p))) { - if(!strcmp(l, "#---------------------------------------------------------------#")) + if(!strcmp(l, "#---------------------------------------------------------------#")) { continue; + } + int len = strcspn(l, "\t ="); + if(len == 4 && !strncasecmp(l, "Name", 4)) { value = l + len; value += strspn(value, "\t "); + if(*value == '=') { value++; value += strspn(value, "\t "); } + l[len] = 0; break; } @@ -527,6 +610,7 @@ static bool finalize_join(meshlink_handle_t *mesh) { } char *b64key = ecdsa_get_base64_public_key(mesh->self->connection->ecdsa); + if(!b64key) { fclose(fh); return false; @@ -555,20 +639,26 @@ static bool finalize_join(meshlink_handle_t *mesh) { static bool invitation_send(void *handle, uint8_t type, const void *data, size_t len) { (void)type; meshlink_handle_t *mesh = handle; + while(len) { int result = send(mesh->sock, data, len, 0); - if(result == -1 && errno == EINTR) + + if(result == -1 && errno == EINTR) { continue; - else if(result <= 0) + } else if(result <= 0) { return false; + } + data += result; len -= result; } + return true; } 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: return sptps_send_record(&(mesh->sptps), 0, mesh->cookie, sizeof(mesh)->cookie); @@ -600,20 +690,25 @@ static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint static bool recvline(meshlink_handle_t *mesh, size_t len) { char *newline = NULL; - if(!mesh->sock) + if(!mesh->sock) { abort(); + } while(!(newline = memchr(mesh->buffer, '\n', mesh->blen))) { int result = recv(mesh->sock, mesh->buffer + mesh->blen, sizeof(mesh)->buffer - mesh->blen, 0); - if(result == -1 && errno == EINTR) + + if(result == -1 && errno == EINTR) { continue; - else if(result <= 0) + } else if(result <= 0) { return false; + } + mesh->blen += result; } - if((size_t)(newline - mesh->buffer) >= len) + if((size_t)(newline - mesh->buffer) >= len) { return false; + } len = newline - mesh->buffer; @@ -634,18 +729,22 @@ static bool sendline(int fd, char *format, ...) { blen = vsnprintf(buffer, sizeof(buffer), format, ap); va_end(ap); - if(blen < 1 || (size_t)blen >= sizeof(buffer)) + if(blen < 1 || (size_t)blen >= sizeof(buffer)) { return false; + } buffer[blen] = '\n'; blen++; while(blen) { int result = send(fd, p, blen, MSG_NOSIGNAL); - if(result == -1 && errno == EINTR) + + if(result == -1 && errno == EINTR) { continue; - else if(result <= 0) + } else if(result <= 0) { return false; + } + p += result; blen -= result; } @@ -667,8 +766,10 @@ static const char *errstr[] = { }; const char *meshlink_strerror(meshlink_errno_t err) { - if((int)err < 0 || err >= sizeof(errstr) / sizeof(*errstr)) + if((int)err < 0 || err >= sizeof(errstr) / sizeof(*errstr)) { return "Invalid error code"; + } + return errstr[err]; } @@ -683,8 +784,9 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) { logger(mesh, MESHLINK_DEBUG, "Error during key generation!\n"); meshlink_errno = MESHLINK_EINTERNAL; return false; - } else + } else { logger(mesh, MESHLINK_DEBUG, "Done.\n"); + } snprintf(privname, sizeof(privname), "%s" SLASH "ecdsa_key.priv", mesh->confbase); f = fopen(privname, "wb"); @@ -730,13 +832,19 @@ static struct timeval idle(event_loop_t *loop, void *data) { (void)loop; meshlink_handle_t *mesh = data; struct timeval t, tmin = {3600, 0}; + for splay_each(node_t, n, mesh->nodes) { - if(!n->utcp) + if(!n->utcp) { continue; + } + t = utcp_timeout(n->utcp); - if(timercmp(&t, &tmin, <)) + + if(timercmp(&t, &tmin, <)) { tmin = t; + } } + return tmin; } @@ -751,10 +859,12 @@ static bool getlocaladdrname(char *destaddr, char *host, socklen_t hostlen) { .ai_protocol = IPPROTO_UDP, }; - if(getaddrinfo(destaddr, "80", &hint, &rai) || !rai) + if(getaddrinfo(destaddr, "80", &hint, &rai) || !rai) { return false; + } int sock = socket(rai->ai_family, rai->ai_socktype, rai->ai_protocol); + if(sock == -1) { freeaddrinfo(rai); return false; @@ -770,11 +880,13 @@ static bool getlocaladdrname(char *destaddr, char *host, socklen_t hostlen) { struct sockaddr_storage sn; socklen_t sl = sizeof(sn); - if(getsockname(sock, (struct sockaddr *)&sn, &sl)) + if(getsockname(sock, (struct sockaddr *)&sn, &sl)) { return false; + } - if(getnameinfo((struct sockaddr *)&sn, sl, host, hostlen, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) + if(getnameinfo((struct sockaddr *)&sn, sl, host, hostlen, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) { return false; + } return true; } @@ -824,6 +936,7 @@ static bool meshlink_setup(meshlink_handle_t *mesh) { } FILE *f = fopen(filename, "w"); + if(!f) { logger(mesh, MESHLINK_DEBUG, "Could not create file %s: %s\n", filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; @@ -870,8 +983,9 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const c logger(NULL, MESHLINK_ERROR, "Invalid name given!\n"); meshlink_errno = MESHLINK_EINVAL; return NULL; - } else + } else { usingname = true; + } } if((int)devclass < 0 || devclass > _DEV_CLASS_MAX) { @@ -884,7 +998,10 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const c mesh->confbase = xstrdup(confbase); mesh->appname = xstrdup(appname); mesh->devclass = devclass; - if(usingname) mesh->name = xstrdup(name); + + if(usingname) { + mesh->name = xstrdup(name); + } // initialize mutex pthread_mutexattr_t attr; @@ -928,7 +1045,9 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const c #ifdef HAVE_MINGW struct WSAData wsa_state; + WSAStartup(MAKEWORD(2, 2), &wsa_state); + #endif // Setup up everything @@ -1011,8 +1130,9 @@ bool meshlink_start(meshlink_handle_t *mesh) { mesh->threadstarted = true; - if(mesh->discovery) + if(mesh->discovery) { discovery_start(mesh); + } pthread_mutex_unlock(&(mesh->mesh_mutex)); return true; @@ -1028,16 +1148,19 @@ void meshlink_stop(meshlink_handle_t *mesh) { logger(mesh, MESHLINK_DEBUG, "meshlink_stop called\n"); // Stop discovery - if(mesh->discovery) + if(mesh->discovery) { discovery_stop(mesh); + } // Shut down the main thread event_loop_stop(&mesh->loop); // Send ourselves a UDP packet to kick the event loop listen_socket_t *s = &mesh->listen_socket[0]; - if(sendto(s->udp.fd, "", 1, MSG_NOSIGNAL, &s->sa.sa, SALEN(s->sa.sa)) == -1) + + if(sendto(s->udp.fd, "", 1, MSG_NOSIGNAL, &s->sa.sa, SALEN(s->sa.sa)) == -1) { logger(mesh, MESHLINK_ERROR, "Could not send a UDP packet to ourself"); + } // Wait for the main thread to finish pthread_mutex_unlock(&(mesh->mesh_mutex)); @@ -1056,8 +1179,10 @@ void meshlink_stop(meshlink_handle_t *mesh) { } } - if(mesh->outgoings) + if(mesh->outgoings) { list_delete_list(mesh->outgoings); + } + mesh->outgoings = NULL; pthread_mutex_unlock(&(mesh->mesh_mutex)); @@ -1085,8 +1210,11 @@ void meshlink_close(meshlink_handle_t *mesh) { event_loop_exit(&mesh->loop); #ifdef HAVE_MINGW - if(mesh->confbase) + + if(mesh->confbase) { WSACleanup(); + } + #endif ecdsa_free(mesh->invitation_key); @@ -1103,18 +1231,26 @@ void meshlink_close(meshlink_handle_t *mesh) { static void deltree(const char *dirname) { DIR *d = opendir(dirname); + if(d) { struct dirent *ent; + while((ent = readdir(d))) { - if(ent->d_name[0] == '.') + if(ent->d_name[0] == '.') { continue; + } + char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s" SLASH "%s", dirname, ent->d_name); - if(unlink(filename)) + + if(unlink(filename)) { deltree(filename); + } } + closedir(d); } + rmdir(dirname); return; } @@ -1187,8 +1323,9 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const return false; } - if(!len) + if(!len) { return true; + } if(!data) { meshlink_errno = MESHLINK_EINVAL; @@ -1197,6 +1334,7 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const // Prepare the packet vpn_packet_t *packet = malloc(sizeof(*packet)); + if(!packet) { meshlink_errno = MESHLINK_ENOMEM; return false; @@ -1231,8 +1369,10 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const void meshlink_send_from_queue(event_loop_t *loop, meshlink_handle_t *mesh) { (void)loop; vpn_packet_t *packet = meshlink_queue_pop(&mesh->outpacketqueue); - if(!packet) + + if(!packet) { return; + } mesh->self->in_packets++; mesh->self->in_bytes += packet->len; @@ -1244,9 +1384,11 @@ ssize_t meshlink_get_pmtu(meshlink_handle_t *mesh, meshlink_node_t *destination) meshlink_errno = MESHLINK_EINVAL; return -1; } + pthread_mutex_lock(&(mesh->mesh_mutex)); node_t *n = (node_t *)destination; + if(!n->status.reachable) { pthread_mutex_unlock(&(mesh->mesh_mutex)); return 0; @@ -1265,6 +1407,7 @@ char *meshlink_get_fingerprint(meshlink_handle_t *mesh, meshlink_node_t *node) { meshlink_errno = MESHLINK_EINVAL; return NULL; } + pthread_mutex_lock(&(mesh->mesh_mutex)); node_t *n = (node_t *)node; @@ -1277,8 +1420,9 @@ char *meshlink_get_fingerprint(meshlink_handle_t *mesh, meshlink_node_t *node) { char *fingerprint = ecdsa_get_base64_public_key(n->ecdsa); - if(!fingerprint) + if(!fingerprint) { meshlink_errno = MESHLINK_EINTERNAL; + } pthread_mutex_unlock(&(mesh->mesh_mutex)); return fingerprint; @@ -1323,8 +1467,10 @@ meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_ if(result) { meshlink_node_t **p = result; - for splay_each(node_t, n, mesh->nodes) + + for splay_each(node_t, n, mesh->nodes) { *p++ = (meshlink_node_t *)n; + } } else { *nmemb = 0; free(nodes); @@ -1377,11 +1523,14 @@ bool meshlink_verify(meshlink_handle_t *mesh, meshlink_node_t *source, const voi struct node_t *n = (struct node_t *)source; node_read_ecdsa_public_key(mesh, n); + if(!n->ecdsa) { meshlink_errno = MESHLINK_EINTERNAL; rval = false; - } else + } else { rval = ecdsa_verify(((struct node_t *)source)->ecdsa, data, len, signature); + } + pthread_mutex_unlock(&(mesh->mesh_mutex)); return rval; } @@ -1392,6 +1541,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) { pthread_mutex_lock(&(mesh->mesh_mutex)); snprintf(filename, sizeof(filename), "%s" SLASH "invitations", mesh->confbase); + if(mkdir(filename, 0700) && errno != EEXIST) { logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; @@ -1401,6 +1551,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) { // Count the number of valid invitations, clean up old ones DIR *dir = opendir(filename); + if(!dir) { logger(mesh, MESHLINK_DEBUG, "Could not read directory %s: %s\n", filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; @@ -1414,16 +1565,20 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) { time_t deadline = time(NULL) - 604800; // 1 week in the past while((ent = readdir(dir))) { - if(strlen(ent->d_name) != 24) + if(strlen(ent->d_name) != 24) { continue; + } + char invname[PATH_MAX]; struct stat st; snprintf(invname, sizeof(invname), "%s" SLASH "%s", filename, ent->d_name); + if(!stat(invname, &st)) { - if(mesh->invitation_key && deadline < st.st_mtime) + if(mesh->invitation_key && deadline < st.st_mtime) { count++; - else + } else { unlink(invname); + } } else { logger(mesh, MESHLINK_DEBUG, "Could not stat %s: %s\n", invname, strerror(errno)); errno = 0; @@ -1445,6 +1600,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) { // Remove the key if there are no outstanding invitations. if(!count) { unlink(filename); + if(mesh->invitation_key) { ecdsa_free(mesh->invitation_key); mesh->invitation_key = NULL; @@ -1458,6 +1614,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) { // Create a new key if necessary. FILE *f = fopen(filename, "rb"); + if(!f) { if(errno != ENOENT) { logger(mesh, MESHLINK_DEBUG, "Could not read %s: %s\n", filename, strerror(errno)); @@ -1467,25 +1624,30 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) { } mesh->invitation_key = ecdsa_generate(); + if(!mesh->invitation_key) { logger(mesh, MESHLINK_DEBUG, "Could not generate a new key!\n"); meshlink_errno = MESHLINK_EINTERNAL; pthread_mutex_unlock(&(mesh->mesh_mutex)); return false; } + f = fopen(filename, "wb"); + if(!f) { logger(mesh, MESHLINK_DEBUG, "Could not write %s: %s\n", filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; pthread_mutex_unlock(&(mesh->mesh_mutex)); return false; } + chmod(filename, 0600); ecdsa_write_pem_private_key(mesh->invitation_key, f); fclose(f); } else { mesh->invitation_key = ecdsa_read_pem_private_key(f); fclose(f); + if(!mesh->invitation_key) { logger(mesh, MESHLINK_DEBUG, "Could not read private key from %s\n", filename); meshlink_errno = MESHLINK_ESTORAGE; @@ -1524,8 +1686,10 @@ bool meshlink_add_external_address(meshlink_handle_t *mesh) { } char *address = meshlink_get_external_address(mesh); - if(!address) + + if(!address) { return false; + } bool rval = false; @@ -1557,8 +1721,9 @@ bool meshlink_set_port(meshlink_handle_t *mesh, int port) { return false; } - if(mesh->myport && port == atoi(mesh->myport)) + if(mesh->myport && port == atoi(mesh->myport)) { return true; + } if(!try_bind(port)) { meshlink_errno = MESHLINK_ENETWORK; @@ -1568,6 +1733,7 @@ bool meshlink_set_port(meshlink_handle_t *mesh, int port) { bool rval = false; pthread_mutex_lock(&(mesh->mesh_mutex)); + if(mesh->threadstarted) { meshlink_errno = MESHLINK_EINVAL; goto done; @@ -1584,12 +1750,13 @@ bool meshlink_set_port(meshlink_handle_t *mesh, int port) { init_configuration(&mesh->config); - if(!read_server_config(mesh)) + if(!read_server_config(mesh)) { meshlink_errno = MESHLINK_ESTORAGE; - else if(!setup_network(mesh)) + } else if(!setup_network(mesh)) { meshlink_errno = MESHLINK_ENETWORK; - else + } else { rval = true; + } done: pthread_mutex_unlock(&(mesh->mesh_mutex)); @@ -1616,6 +1783,7 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) { // Ensure no host configuration file with that name exists char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name); + if(!access(filename, F_OK)) { logger(mesh, MESHLINK_DEBUG, "A host config file for %s already exists!\n", name); meshlink_errno = MESHLINK_EEXIST; @@ -1633,6 +1801,7 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) { // Get the local address char *address = get_my_hostname(mesh); + if(!address) { logger(mesh, MESHLINK_DEBUG, "No Address known for ourselves!\n"); meshlink_errno = MESHLINK_ERESOLV; @@ -1672,15 +1841,19 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) { // Create a file containing the details of the invitation. snprintf(filename, sizeof(filename), "%s" SLASH "invitations" SLASH "%s", mesh->confbase, cookiehash); int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); + if(!ifd) { logger(mesh, MESHLINK_DEBUG, "Could not create invitation file %s: %s\n", filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; pthread_mutex_unlock(&(mesh->mesh_mutex)); return NULL; } + FILE *f = fdopen(ifd, "w"); - if(!f) + + if(!f) { abort(); + } // Fill in the details. fprintf(f, "Name = %s\n", name); @@ -1691,17 +1864,22 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) { // Copy Broadcast and Mode snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", mesh->confbase); FILE *tc = fopen(filename, "r"); + if(tc) { char buf[1024]; + while(fgets(buf, sizeof(buf), tc)) { if((!strncasecmp(buf, "Mode", 4) && strchr(" \t=", buf[4])) || (!strncasecmp(buf, "Broadcast", 9) && strchr(" \t=", buf[9]))) { fputs(buf, f); + // Make sure there is a newline character. - if(!strchr(buf, '\n')) + if(!strchr(buf, '\n')) { fputc('\n', f); + } } } + fclose(tc); } else { logger(mesh, MESHLINK_DEBUG, "Could not create %s: %s\n", filename, strerror(errno)); @@ -1741,38 +1919,52 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { // Split the invitation URL into hostname, port, key hash and cookie. char *slash = strchr(copy, '/'); - if(!slash) + + if(!slash) { goto invalid; + } *slash++ = 0; - if(strlen(slash) != 48) + if(strlen(slash) != 48) { goto invalid; + } char *address = copy; char *port = NULL; + if(*address == '[') { address++; char *bracket = strchr(address, ']'); - if(!bracket) + + if(!bracket) { goto invalid; + } + *bracket = 0; - if(bracket[1] == ':') + + if(bracket[1] == ':') { port = bracket + 2; + } } else { port = strchr(address, ':'); - if(port) + + if(port) { *port++ = 0; + } } - if(!port) + if(!port) { goto invalid; + } - if(!b64decode(slash, mesh->hash, 18) || !b64decode(slash + 24, mesh->cookie, 18)) + if(!b64decode(slash, mesh->hash, 18) || !b64decode(slash + 24, mesh->cookie, 18)) { goto invalid; + } // Generate a throw-away key for the invitation. ecdsa_t *key = ecdsa_generate(); + if(!key) { meshlink_errno = MESHLINK_EINTERNAL; pthread_mutex_unlock(&(mesh->mesh_mutex)); @@ -1782,11 +1974,13 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { char *b64key = ecdsa_get_base64_public_key(key); //Before doing meshlink_join make sure we are not connected to another mesh - if(mesh->threadstarted) + if(mesh->threadstarted) { goto invalid; + } // Connect to the meshlink daemon mentioned in the URL. struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM); + if(!ai) { meshlink_errno = MESHLINK_ERESOLV; pthread_mutex_unlock(&(mesh->mesh_mutex)); @@ -1794,6 +1988,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { } mesh->sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if(mesh->sock <= 0) { logger(mesh, MESHLINK_DEBUG, "Could not open socket: %s\n", strerror(errno)); freeaddrinfo(ai); @@ -1845,12 +2040,14 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { // Check if the hash of the key he gave us matches the hash in the URL. char *fingerprint = mesh->line + 2; char hishash[64]; + if(sha512(fingerprint, strlen(fingerprint), hishash)) { logger(mesh, MESHLINK_DEBUG, "Could not create hash\n%s\n", mesh->line + 2); meshlink_errno = MESHLINK_EINTERNAL; pthread_mutex_unlock(&(mesh->mesh_mutex)); return false; } + if(memcmp(hishash, mesh->hash, 18)) { logger(mesh, MESHLINK_DEBUG, "Peer has an invalid key!\n%s\n", mesh->line + 2); meshlink_errno = MESHLINK_EPEER; @@ -1860,6 +2057,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { } ecdsa_t *hiskey = ecdsa_set_base64_public_key(fingerprint); + if(!hiskey) { meshlink_errno = MESHLINK_EINTERNAL; pthread_mutex_unlock(&(mesh->mesh_mutex)); @@ -1884,8 +2082,10 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { while((len = recv(mesh->sock, mesh->line, sizeof(mesh)->line, 0))) { if(len < 0) { - if(errno == EINTR) + if(errno == EINTR) { continue; + } + logger(mesh, MESHLINK_DEBUG, "Error reading data from %s port %s: %s\n", address, port, strerror(errno)); meshlink_errno = MESHLINK_ENETWORK; pthread_mutex_unlock(&(mesh->mesh_mutex)); @@ -1932,6 +2132,7 @@ char *meshlink_export(meshlink_handle_t *mesh) { 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) { logger(mesh, MESHLINK_DEBUG, "Could not open %s: %s\n", filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; @@ -1946,6 +2147,7 @@ char *meshlink_export(meshlink_handle_t *mesh) { 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) { logger(mesh, MESHLINK_DEBUG, "Error reading from %s: %s\n", filename, strerror(errno)); fclose(f); @@ -1978,6 +2180,7 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) { } char *end = strchr(data + 7, '\n'); + if(!end) { logger(mesh, MESHLINK_DEBUG, "Invalid data\n"); meshlink_errno = MESHLINK_EPEER; @@ -1989,6 +2192,7 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) { char name[len + 1]; memcpy(name, data + 7, len); name[len] = 0; + if(!check_id(name)) { logger(mesh, MESHLINK_DEBUG, "Invalid Name\n"); meshlink_errno = MESHLINK_EPEER; @@ -1998,6 +2202,7 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) { char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name); + if(!access(filename, F_OK)) { logger(mesh, MESHLINK_DEBUG, "File %s already exists, not importing\n", filename); meshlink_errno = MESHLINK_EEXIST; @@ -2013,6 +2218,7 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) { } FILE *f = fopen(filename, "w"); + if(!f) { logger(mesh, MESHLINK_DEBUG, "Could not create %s: %s\n", filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; @@ -2074,12 +2280,14 @@ void meshlink_set_default_blacklist(meshlink_handle_t *mesh, bool blacklist) { * See header file for detailed comment. */ void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const struct sockaddr *addr) { - if(!mesh || !node || !addr) + if(!mesh || !node || !addr) { return; + } // Ignore hints about ourself. - if((node_t *)node == mesh->self) + if((node_t *)node == mesh->self) { return; + } pthread_mutex_lock(&(mesh->mesh_mutex)); @@ -2088,10 +2296,12 @@ void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const if(host && port) { xasprintf(&str, "%s %s", host, port); - if((strncmp("fe80", host, 4) != 0) && (strncmp("127.", host, 4) != 0) && (strcmp("localhost", host) != 0)) + + if((strncmp("fe80", host, 4) != 0) && (strncmp("127.", host, 4) != 0) && (strcmp("localhost", host) != 0)) { modify_config_file(mesh, node->name, "Address", str, 5); - else + } else { logger(mesh, MESHLINK_DEBUG, "Not adding Link Local IPv6 Address to config\n"); + } } free(str); @@ -2111,31 +2321,45 @@ static bool channel_pre_accept(struct utcp *utcp, uint16_t port) { static ssize_t channel_recv(struct utcp_connection *connection, const void *data, size_t len) { meshlink_channel_t *channel = connection->priv; - if(!channel) + + if(!channel) { abort(); + } + node_t *n = channel->node; meshlink_handle_t *mesh = n->mesh; - if(n->status.destroyed) + + if(n->status.destroyed) { meshlink_channel_close(mesh, channel); - else if(channel->receive_cb) + } else if(channel->receive_cb) { channel->receive_cb(mesh, channel, data, len); + } + return len; } static void channel_accept(struct utcp_connection *utcp_connection, uint16_t port) { node_t *n = utcp_connection->utcp->priv; - if(!n) + + if(!n) { abort(); + } + meshlink_handle_t *mesh = n->mesh; - if(!mesh->channel_accept_cb) + + if(!mesh->channel_accept_cb) { return; + } + meshlink_channel_t *channel = xzalloc(sizeof(*channel)); channel->node = n; channel->c = utcp_connection; - if(mesh->channel_accept_cb(mesh, channel, port, NULL, 0)) + + if(mesh->channel_accept_cb(mesh, channel, port, NULL, 0)) { utcp_accept(utcp_connection, channel_recv, channel); - else + } else { free(channel); + } } static ssize_t channel_send(struct utcp *utcp, const void *data, size_t len) { @@ -2156,19 +2380,27 @@ void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t static void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) { (void)mesh; node_t *n = (node_t *)source; - if(!n->utcp) + + if(!n->utcp) { abort(); + } + utcp_recv(n->utcp, data, len); } static void channel_poll(struct utcp_connection *connection, size_t len) { meshlink_channel_t *channel = connection->priv; - if(!channel) + + if(!channel) { abort(); + } + node_t *n = channel->node; meshlink_handle_t *mesh = n->mesh; - if(channel->poll_cb) + + if(channel->poll_cb) { channel->poll_cb(mesh, channel, len); + } } void meshlink_set_channel_poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_poll_cb_t cb) { @@ -2186,16 +2418,20 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac pthread_mutex_lock(&mesh->mesh_mutex); mesh->channel_accept_cb = cb; mesh->receive_cb = channel_receive; + for splay_each(node_t, n, mesh->nodes) { - if(!n->utcp && n != mesh->self) + if(!n->utcp && n != mesh->self) { n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); + } } + pthread_mutex_unlock(&mesh->mesh_mutex); } meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_node_t *node, uint16_t port, meshlink_channel_receive_cb_t cb, const void *data, size_t len, uint32_t flags) { - if(data || len) - abort(); // TODO: handle non-NULL data + if(data || len) { + abort(); // TODO: handle non-NULL data + } if(!mesh || !node) { meshlink_errno = MESHLINK_EINVAL; @@ -2203,23 +2439,28 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n } node_t *n = (node_t *)node; + if(!n->utcp) { n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); mesh->receive_cb = channel_receive; + if(!n->utcp) { meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL; return NULL; } } + meshlink_channel_t *channel = xzalloc(sizeof(*channel)); channel->node = n; channel->receive_cb = cb; channel->c = utcp_connect_ex(n->utcp, port, channel_recv, channel, flags); + if(!channel->c) { meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL; free(channel); return NULL; } + return channel; } @@ -2252,8 +2493,9 @@ ssize_t meshlink_channel_send(meshlink_handle_t *mesh, meshlink_channel_t *chann return -1; } - if(!len) + if(!len) { return 0; + } if(!data) { meshlink_errno = MESHLINK_EINVAL; @@ -2269,8 +2511,10 @@ ssize_t meshlink_channel_send(meshlink_handle_t *mesh, meshlink_channel_t *chann ssize_t retval = utcp_send(channel->c, data, len); pthread_mutex_unlock(&mesh->mesh_mutex); - if(retval < 0) + if(retval < 0) { meshlink_errno = MESHLINK_ENETWORK; + } + return retval; } @@ -2284,10 +2528,13 @@ uint32_t meshlink_channel_get_flags(meshlink_handle_t *mesh, meshlink_channel_t } void update_node_status(meshlink_handle_t *mesh, node_t *n) { - if(n->status.reachable && mesh->channel_accept_cb && !n->utcp) + if(n->status.reachable && mesh->channel_accept_cb && !n->utcp) { n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); - if(mesh->node_status_cb) + } + + if(mesh->node_status_cb) { mesh->node_status_cb(mesh, (meshlink_node_t *)n, n->status.reachable); + } } void meshlink_enable_discovery(meshlink_handle_t *mesh, bool enable) { @@ -2298,14 +2545,16 @@ void meshlink_enable_discovery(meshlink_handle_t *mesh, bool enable) { pthread_mutex_lock(&mesh->mesh_mutex); - if(mesh->discovery == enable) + if(mesh->discovery == enable) { goto end; + } if(mesh->threadstarted) { - if(enable) + if(enable) { discovery_start(mesh); - else + } else { discovery_stop(mesh); + } } mesh->discovery = enable; diff --git a/src/meshlink_queue.h b/src/meshlink_queue.h index a713f93f..fc751a8f 100644 --- a/src/meshlink_queue.h +++ b/src/meshlink_queue.h @@ -38,15 +38,21 @@ typedef struct meshlink_queue_item { static inline bool meshlink_queue_push(meshlink_queue_t *queue, void *data) { meshlink_queue_item_t *item = malloc(sizeof(*item)); - if(!item) + + if(!item) { return false; + } + item->data = data; item->next = NULL; pthread_mutex_lock(&queue->mutex); - if(!queue->tail) + + if(!queue->tail) { queue->head = queue->tail = item; - else + } else { queue->tail = queue->tail->next = item; + } + pthread_mutex_unlock(&queue->mutex); return true; } @@ -55,11 +61,15 @@ static inline void *meshlink_queue_pop(meshlink_queue_t *queue) { meshlink_queue_item_t *item; void *data; pthread_mutex_lock(&queue->mutex); + if((item = queue->head)) { queue->head = item->next; - if(!queue->head) + + if(!queue->head) { queue->tail = NULL; + } } + pthread_mutex_unlock(&queue->mutex); data = item ? item->data : NULL; free(item); diff --git a/src/meta.c b/src/meta.c index fe213643..68450166 100644 --- a/src/meta.c +++ b/src/meta.c @@ -63,8 +63,9 @@ bool send_meta(meshlink_handle_t *mesh, connection_t *c, const char *buffer, int void broadcast_meta(meshlink_handle_t *mesh, connection_t *from, const char *buffer, int length) { for list_each(connection_t, c, mesh->connections) - if(c != from && c->status.active) + if(c != from && c->status.active) { send_meta(mesh, c, buffer, length); + } } bool receive_meta_sptps(void *handle, uint8_t type, const void *data, uint16_t length) { @@ -78,14 +79,16 @@ bool receive_meta_sptps(void *handle, uint8_t type, const void *data, uint16_t l } if(type == SPTPS_HANDSHAKE) { - if(c->allow_request == ACK) + if(c->allow_request == ACK) { return send_ack(mesh, c); - else + } else { return true; + } } - if(!request) + if(!request) { return true; + } /* Are we receiving a TCPpacket? */ @@ -95,8 +98,9 @@ bool receive_meta_sptps(void *handle, uint8_t type, const void *data, uint16_t l /* Change newline to null byte, just like non-SPTPS requests */ - if(request[length - 1] == '\n') + if(request[length - 1] == '\n') { request[length - 1] = 0; + } /* Otherwise we are waiting for a request */ @@ -112,10 +116,12 @@ bool receive_meta(meshlink_handle_t *mesh, connection_t *c) { if(inlen <= 0) { if(!inlen || !errno) { logger(mesh, MESHLINK_INFO, "Connection closed by %s", c->name); - } else if(sockwouldblock(sockerrno)) + } else if(sockwouldblock(sockerrno)) { return true; - else + } else { logger(mesh, MESHLINK_ERROR, "Metadata socket read error for %s: %s", c->name, sockstrerror(sockerrno)); + } + return false; } @@ -125,22 +131,26 @@ bool receive_meta(meshlink_handle_t *mesh, connection_t *c) { char *request = buffer_readline(&c->inbuf); if(request) { - if(!receive_request(mesh, c, request) || c->allow_request == ID) + if(!receive_request(mesh, c, request) || c->allow_request == ID) { return false; + } int left = c->inbuf.len - c->inbuf.offset; + if(left > 0) { fprintf(stderr, "GOT A LITTLE MORE\n"); return sptps_receive_data(&c->sptps, buffer_read(&c->inbuf, left), left); - } else + } else { return true; + } } if(c->inbuf.len >= sizeof(inbuf)) { logger(mesh, MESHLINK_ERROR, "Input buffer full for %s", c->name); return false; - } else + } else { return true; + } } return sptps_receive_data(&c->sptps, inbuf, inlen); diff --git a/src/net.c b/src/net.c index 69462d5c..84625917 100644 --- a/src/net.c +++ b/src/net.c @@ -51,12 +51,14 @@ void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report) c->status.active = false; - if(c->node && c->node->connection == c) + if(c->node && c->node->connection == c) { c->node->connection = NULL; + } if(c->edge) { - if(report) + if(report) { send_del_edge(mesh, mesh->everyone, c->edge); + } edge_del(mesh, c->edge); c->edge = NULL; @@ -70,6 +72,7 @@ void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report) if(report && c->node && !c->node->status.reachable) { edge_t *e; e = lookup_edge(c->node, mesh->self); + if(e) { send_del_edge(mesh, mesh->everyone, e); edge_del(mesh, e); @@ -82,13 +85,15 @@ void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report) /* Check if this was our outgoing connection */ - if(outgoing) + if(outgoing) { do_outgoing_connection(mesh, outgoing); + } #ifndef HAVE_MINGW /* Clean up dead proxy processes */ while(waitpid(-1, NULL, WNOHANG) > 0); + #endif } @@ -107,24 +112,29 @@ static void timeout_handler(event_loop_t *loop, void *data) { for list_each(connection_t, c, mesh->connections) { // Also make sure that if outstanding key requests for the UDP counterpart of a connection has timed out, we restart it. if(c->node) { - if(c->node->status.waitingforkey && c->node->last_req_key + mesh->pingtimeout <= mesh->loop.now.tv_sec) + if(c->node->status.waitingforkey && c->node->last_req_key + mesh->pingtimeout <= mesh->loop.now.tv_sec) { send_req_key(mesh, c->node); + } } + if(c->last_ping_time + mesh->pingtimeout <= mesh->loop.now.tv_sec) { if(c->status.active) { - if(c->status.pinged) + if(c->status.pinged) { logger(mesh, MESHLINK_INFO, "%s didn't respond to PING in %ld seconds", c->name, (long)mesh->loop.now.tv_sec - c->last_ping_time); - else if(c->last_ping_time + mesh->pinginterval <= mesh->loop.now.tv_sec) { + } else if(c->last_ping_time + mesh->pinginterval <= mesh->loop.now.tv_sec) { send_ping(mesh, c); continue; - } else + } else { continue; + } } else { - if(c->status.connecting) + if(c->status.connecting) { logger(mesh, MESHLINK_WARNING, "Timeout while connecting to %s", c->name); - else + } else { logger(mesh, MESHLINK_WARNING, "Timeout from %s during authentication", c->name); + } } + terminate_connection(mesh, c, c->status.active); } } @@ -138,26 +148,33 @@ static void timeout_handler(event_loop_t *loop, void *data) { static int node_compare_devclass_asc_lsc_desc(const void *a, const void *b) { const node_t *na = a, *nb = b; - if(na->devclass < nb->devclass) + if(na->devclass < nb->devclass) { return -1; + } - if(na->devclass > nb->devclass) + if(na->devclass > nb->devclass) { return 1; + } - if(na->last_successfull_connection == nb->last_successfull_connection) + if(na->last_successfull_connection == nb->last_successfull_connection) { return 0; + } - if(na->last_successfull_connection == 0 || na->last_successfull_connection > nb->last_successfull_connection) + if(na->last_successfull_connection == 0 || na->last_successfull_connection > nb->last_successfull_connection) { return -1; + } - if(nb->last_successfull_connection == 0 || na->last_successfull_connection < nb->last_successfull_connection) + if(nb->last_successfull_connection == 0 || na->last_successfull_connection < nb->last_successfull_connection) { return 1; + } - if(na < nb) + if(na < nb) { return -1; + } - if(na > nb) + if(na > nb) { return 1; + } return 0; } @@ -166,20 +183,25 @@ static int node_compare_devclass_asc_lsc_desc(const void *a, const void *b) { static int node_compare_lsc_desc(const void *a, const void *b) { const node_t *na = a, *nb = b; - if(na->last_successfull_connection == nb->last_successfull_connection) + if(na->last_successfull_connection == nb->last_successfull_connection) { return 0; + } - if(na->last_successfull_connection == 0 || na->last_successfull_connection > nb->last_successfull_connection) + if(na->last_successfull_connection == 0 || na->last_successfull_connection > nb->last_successfull_connection) { return -1; + } - if(nb->last_successfull_connection == 0 || na->last_successfull_connection < nb->last_successfull_connection) + if(nb->last_successfull_connection == 0 || na->last_successfull_connection < nb->last_successfull_connection) { return 1; + } - if(na < nb) + if(na < nb) { return -1; + } - if(na > nb) + if(na > nb) { return 1; + } return 0; } @@ -188,17 +210,21 @@ static int node_compare_lsc_desc(const void *a, const void *b) { static int node_compare_devclass_desc(const void *a, const void *b) { const node_t *na = a, *nb = b; - if(na->devclass < nb->devclass) + if(na->devclass < nb->devclass) { return -1; + } - if(na->devclass > nb->devclass) + if(na->devclass > nb->devclass) { return 1; + } - if(na < nb) + if(na < nb) { return -1; + } - if(na > nb) + if(na > nb) { return 1; + } return 0; } @@ -310,12 +336,16 @@ static void periodic_handler(event_loop_t *loop, void *data) { logger(mesh, MESHLINK_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", mesh->sleeptime); usleep(mesh->sleeptime * 1000000LL); mesh->sleeptime *= 2; - if(mesh->sleeptime < 0) + + if(mesh->sleeptime < 0) { mesh->sleeptime = 3600; + } } else { mesh->sleeptime /= 2; - if(mesh->sleeptime < 10) + + if(mesh->sleeptime < 10) { mesh->sleeptime = 10; + } } mesh->contradicting_add_edge = 0; @@ -347,8 +377,9 @@ static void periodic_handler(event_loop_t *loop, void *data) { unsigned int cur_connects = 0; for list_each(connection_t, c, mesh->connections) { - if(c->status.active) + if(c->status.active) { cur_connects += 1; + } } logger(mesh, MESHLINK_DEBUG, "* cur_connects = %d", cur_connects); @@ -372,8 +403,10 @@ static void periodic_handler(event_loop_t *loop, void *data) { for splay_each(node_t, n, mesh->nodes) { logger(mesh, MESHLINK_DEBUG, "* n->devclass = %d", n->devclass); - if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) + + if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); + } } if(nodes->head) { @@ -381,8 +414,9 @@ static void periodic_handler(event_loop_t *loop, void *data) { //timeout = 0; connect_to = (node_t *)nodes->head->data; - } else + } else { logger(mesh, MESHLINK_DEBUG, "* could not find node for initial connect"); + } splay_free_tree(nodes); } @@ -395,16 +429,18 @@ static void periodic_handler(event_loop_t *loop, void *data) { for(unsigned int devclass = 0; devclass <= mesh->devclass; ++devclass) { for list_each(connection_t, c, mesh->connections) { - if(c->status.active && c->node && c->node->devclass == devclass) + if(c->status.active && c->node && c->node->devclass == devclass) { connects += 1; + } } if(connects < min_connects) { splay_tree_t *nodes = splay_alloc_tree(node_compare_lsc_desc, NULL); for splay_each(node_t, n, mesh->nodes) { - if(n != mesh->self && n->devclass == devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) + if(n != mesh->self && n->devclass == devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); + } } if(nodes->head) { @@ -416,12 +452,14 @@ static void periodic_handler(event_loop_t *loop, void *data) { } splay_free_tree(nodes); - } else + } else { break; + } } - if(!connect_to) + if(!connect_to) { logger(mesh, MESHLINK_DEBUG, "* could not find better nodes"); + } } @@ -431,15 +469,17 @@ static void periodic_handler(event_loop_t *loop, void *data) { splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL); for splay_each(node_t, n, mesh->nodes) { - if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) + if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); + } } if(nodes->head) { logger(mesh, MESHLINK_DEBUG, "* try to heal partition"); connect_to = (node_t *)nodes->head->data; - } else + } else { logger(mesh, MESHLINK_DEBUG, "* could not find nodes for partition healing"); + } splay_free_tree(nodes); } @@ -452,6 +492,7 @@ static void periodic_handler(event_loop_t *loop, void *data) { /* check if there is already a connection attempt to this node */ bool found = false; + for list_each(outgoing_t, outgoing, mesh->outgoings) { if(!strcmp(outgoing->name, connect_to->name)) { found = true; @@ -466,8 +507,9 @@ static void periodic_handler(event_loop_t *loop, void *data) { outgoing->name = xstrdup(connect_to->name); list_insert_tail(mesh->outgoings, outgoing); setup_outgoing_connection(mesh, outgoing); - } else + } else { logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since it is an outgoing connection already"); + } } @@ -478,16 +520,18 @@ static void periodic_handler(event_loop_t *loop, void *data) { for(unsigned int devclass = 0; devclass <= mesh->devclass; ++devclass) { for list_each(connection_t, c, mesh->connections) { - if(c->status.active && c->node && c->node->devclass == devclass) + if(c->status.active && c->node && c->node->devclass == devclass) { connects += 1; + } } if(min_connects < connects) { splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_desc, NULL); for list_each(connection_t, c, mesh->connections) { - if(c->outgoing && c->node && c->node->devclass >= devclass) + if(c->outgoing && c->node && c->node->devclass >= devclass) { splay_insert(nodes, c->node); + } } if(nodes->head) { @@ -500,8 +544,9 @@ static void periodic_handler(event_loop_t *loop, void *data) { } } - if(!disconnect_from) + if(!disconnect_from) { logger(mesh, MESHLINK_DEBUG, "* no suboptimal outgoing connections"); + } } @@ -511,8 +556,9 @@ static void periodic_handler(event_loop_t *loop, void *data) { splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_desc, NULL); for list_each(connection_t, c, mesh->connections) { - if(c->status.active && c->node) + if(c->status.active && c->node) { splay_insert(nodes, c->node); + } } if(nodes->head) { @@ -520,8 +566,9 @@ static void periodic_handler(event_loop_t *loop, void *data) { //timeout = 0; disconnect_from = (node_t *)nodes->head->data; - } else + } else { logger(mesh, MESHLINK_DEBUG, "* no node we want to disconnect, even though we have too many connections"); + } splay_free_tree(nodes); } @@ -558,6 +605,7 @@ void retry(meshlink_handle_t *mesh) { /* Reset the reconnection timers for all outgoing connections */ for list_each(outgoing_t, outgoing, mesh->outgoings) { outgoing->timeout = 0; + if(outgoing->ev.cb) timeout_set(&mesh->loop, &outgoing->ev, &(struct timeval) { 0, 0 @@ -566,8 +614,9 @@ void retry(meshlink_handle_t *mesh) { /* Check for outgoing connections that are in progress, and reset their ping timers */ for list_each(connection_t, c, mesh->connections) { - if(c->outgoing && !c->node) + if(c->outgoing && !c->node) { c->last_ping_time = 0; + } } /* Kick the ping timeout handler */ diff --git a/src/net_packet.c b/src/net_packet.c index 96f16d57..1ce239d9 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -91,10 +91,12 @@ static void send_mtu_probe_handler(event_loop_t *loop, void *data) { } if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) { - if(n->minmtu > n->maxmtu) + if(n->minmtu > n->maxmtu) { n->minmtu = n->maxmtu; - else + } else { n->maxmtu = n->minmtu; + } + n->mtu = n->minmtu; logger(mesh, MESHLINK_INFO, "Fixing MTU of %s to %d after %d probes", n->name, n->mtu, n->mtuprobes); n->mtuprobes = 31; @@ -103,23 +105,28 @@ static void send_mtu_probe_handler(event_loop_t *loop, void *data) { if(n->mtuprobes == 31) { timeout = mesh->pinginterval; goto end; - } else if(n->mtuprobes == 32) + } else if(n->mtuprobes == 32) { timeout = mesh->pingtimeout; + } for(int i = 0; i < 4 + mesh->localdiscovery; i++) { int len; if(i == 0) { - if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) + if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) { continue; + } + len = n->maxmtu + 8; - } else if(n->maxmtu <= n->minmtu) + } else if(n->maxmtu <= n->minmtu) { len = n->maxmtu; - else + } else { len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); + } - if(len < 64) + if(len < 64) { len = 64; + } vpn_packet_t packet; packet.probe = true; @@ -180,18 +187,22 @@ static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet return; } - if(n->minmtu) + if(n->minmtu) { n->mtuprobes = 30; - else + } else { n->mtuprobes = 1; + } } /* If applicable, raise the minimum supported MTU */ - if(len > n->maxmtu) + if(len > n->maxmtu) { len = n->maxmtu; - if(n->minmtu < len) + } + + if(n->minmtu < len) { n->minmtu = len; + } } } @@ -200,9 +211,9 @@ static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet static void receive_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) { logger(mesh, MESHLINK_DEBUG, "Received packet of %d bytes from %s", packet->len, n->name); - if(n->status.blacklisted) + if(n->status.blacklisted) { logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name); - else { + } else { n->in_packets++; n->in_bytes += packet->len; @@ -220,24 +231,29 @@ static void receive_udppacket(meshlink_handle_t *mesh, node_t *n, vpn_packet_t * if(!n->status.waitingforkey) { logger(mesh, MESHLINK_DEBUG, "Got packet from %s but we haven't exchanged keys yet", n->name); send_req_key(mesh, n); - } else + } else { logger(mesh, MESHLINK_DEBUG, "Got packet from %s but he hasn't got our key yet", n->name); + } + return; } + sptps_receive_data(&n->sptps, inpkt->data, inpkt->len); } static void send_sptps_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *origpkt) { if(!n->status.validkey) { logger(mesh, MESHLINK_INFO, "No valid key known yet for %s", n->name); - if(!n->status.waitingforkey) + + if(!n->status.waitingforkey) { send_req_key(mesh, n); - else if(n->last_req_key + 10 < mesh->loop.now.tv_sec) { + } else if(n->last_req_key + 10 < mesh->loop.now.tv_sec) { logger(mesh, MESHLINK_DEBUG, "No key from %s after 10 seconds, restarting SPTPS", n->name); sptps_stop(&n->sptps); n->status.waitingforkey = false; send_req_key(mesh, n); } + return; } @@ -264,14 +280,16 @@ static void choose_udp_address(meshlink_handle_t *mesh, const node_t *n, const s *sock = n->sock; /* If the UDP address is confirmed, use it. */ - if(n->status.udp_confirmed) + if(n->status.udp_confirmed) { return; + } /* Send every third packet to n->address; that could be set to the node's reflexive UDP address discovered during key exchange. */ static int x = 0; + if(++x >= 3) { x = 0; return; @@ -364,13 +382,15 @@ bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) { if(type >= SPTPS_HANDSHAKE || ((mesh->self->options | to->options) & OPTION_TCPONLY) || (type != PKT_PROBE && len > to->minmtu)) { char buf[len * 4 / 3 + 5]; b64encode(data, buf, len); + /* If no valid key is known yet, send the packets using ANS_KEY requests, to ensure we get to learn the reflexive UDP address. */ if(!to->status.validkey) { to->incompression = mesh->self->incompression; return send_request(mesh, to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, to->incompression); - } else + } else { return send_request(mesh, to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf); + } } /* Otherwise, send the packet via UDP */ @@ -378,17 +398,21 @@ bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) { const sockaddr_t *sa; int sock; - if(to->status.broadcast) + if(to->status.broadcast) { choose_broadcast_address(mesh, to, &sa, &sock); - else + } else { choose_udp_address(mesh, to, &sa, &sock); + } if(sendto(mesh->listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { if(sockmsgsize(sockerrno)) { - if(to->maxmtu >= len) + if(to->maxmtu >= len) { to->maxmtu = len - 1; - if(to->mtu >= len) + } + + if(to->mtu >= len) { to->mtu = len - 1; + } } else { logger(mesh, MESHLINK_WARNING, "Error sending UDP SPTPS packet to %s: %s", to->name, sockstrerror(sockerrno)); return false; @@ -407,9 +431,12 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t logger(mesh, MESHLINK_INFO, "SPTPS key exchange with %s succesful", from->name); from->status.validkey = true; from->status.waitingforkey = false; - if(from->utcp) + + if(from->utcp) { utcp_reset_timers(from->utcp); + } } + return true; } @@ -426,8 +453,9 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t memcpy(inpkt.data, data, len); mtu_probe_h(mesh, from, &inpkt, len); return true; - } else + } else { inpkt.probe = false; + } if(type & ~(PKT_COMPRESSED)) { logger(mesh, MESHLINK_ERROR, "Unexpected SPTPS record type %d len %d from %s", type, len, from->name); @@ -475,14 +503,16 @@ void send_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) { void broadcast_packet(meshlink_handle_t *mesh, const node_t *from, vpn_packet_t *packet) { // Always give ourself a copy of the packet. - if(from != mesh->self) + if(from != mesh->self) { send_packet(mesh, mesh->self, packet); + } logger(mesh, MESHLINK_INFO, "Broadcasting packet of %d bytes from %s", packet->len, from->name); for list_each(connection_t, c, mesh->connections) - if(c->status.active && c->status.mst && c != from->nexthop->connection) + if(c->status.active && c->status.mst && c != from->nexthop->connection) { send_packet(mesh, c->node, packet); + } } static node_t *try_harder(meshlink_handle_t *mesh, const sockaddr_t *from, const vpn_packet_t *pkt) { @@ -491,24 +521,29 @@ static node_t *try_harder(meshlink_handle_t *mesh, const sockaddr_t *from, const static time_t last_hard_try = 0; for splay_each(edge_t, e, mesh->edges) { - if(!e->to->status.reachable || e->to == mesh->self) + if(!e->to->status.reachable || e->to == mesh->self) { continue; + } if(sockaddrcmp_noport(from, &e->address)) { - if(last_hard_try == mesh->loop.now.tv_sec) + if(last_hard_try == mesh->loop.now.tv_sec) { continue; + } + hard = true; } - if(!try_mac(mesh, e->to, pkt)) + if(!try_mac(mesh, e->to, pkt)) { continue; + } n = e->to; break; } - if(hard) + if(hard) { last_hard_try = mesh->loop.now.tv_sec; + } last_hard_try = mesh->loop.now.tv_sec; return n; @@ -528,8 +563,10 @@ void handle_incoming_vpn_data(event_loop_t *loop, void *data, int flags) { len = recvfrom(ls->udp.fd, pkt.data, MAXSIZE, 0, &from.sa, &fromlen); if(len <= 0 || len > MAXSIZE) { - if(!sockwouldblock(sockerrno)) + if(!sockwouldblock(sockerrno)) { logger(mesh, MESHLINK_ERROR, "Receiving packet failed: %s", sockstrerror(sockerrno)); + } + return; } @@ -541,21 +578,24 @@ void handle_incoming_vpn_data(event_loop_t *loop, void *data, int flags) { if(!n) { n = try_harder(mesh, &from, &pkt); - if(n) + + if(n) { update_node_udp(mesh, n, &from); - else if(mesh->log_level >= MESHLINK_WARNING) { + } else if(mesh->log_level >= MESHLINK_WARNING) { hostname = sockaddr2hostname(&from); logger(mesh, MESHLINK_WARNING, "Received UDP packet from unknown source %s", hostname); free(hostname); return; - } else + } else { return; + } } if(n->status.blacklisted) { logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name); return; } + n->sock = ls - mesh->listen_socket; receive_udppacket(mesh, n, &pkt); diff --git a/src/net_setup.c b/src/net_setup.c index 37644c44..a59632cf 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -33,15 +33,18 @@ #include "xalloc.h" bool node_read_ecdsa_public_key(meshlink_handle_t *mesh, node_t *n) { - if(ecdsa_active(n->ecdsa)) + if(ecdsa_active(n->ecdsa)) { return true; + } splay_tree_t *config_tree; char *p; init_configuration(&config_tree); - if(!read_host_config(mesh, config_tree, n->name)) + + if(!read_host_config(mesh, config_tree, n->name)) { goto exit; + } /* First, check for simple ECDSAPublicKey statement */ @@ -56,15 +59,18 @@ exit: } bool read_ecdsa_public_key(meshlink_handle_t *mesh, connection_t *c) { - if(ecdsa_active(c->ecdsa)) + if(ecdsa_active(c->ecdsa)) { return true; + } char *p; if(!c->config_tree) { init_configuration(&c->config_tree); - if(!read_host_config(mesh, c->config_tree, c->name)) + + if(!read_host_config(mesh, c->config_tree, c->name)) { return false; + } } /* First, check for simple ECDSAPublicKey statement */ @@ -93,8 +99,9 @@ bool read_ecdsa_private_key(meshlink_handle_t *mesh) { mesh->self->connection->ecdsa = ecdsa_read_pem_private_key(fp); fclose(fp); - if(!mesh->self->connection->ecdsa) + if(!mesh->self->connection->ecdsa) { logger(mesh, MESHLINK_ERROR, "Reading ECDSA private key file failed: %s", strerror(errno)); + } return mesh->self->connection->ecdsa; } @@ -115,8 +122,10 @@ static bool read_invitation_key(meshlink_handle_t *mesh) { if(fp) { mesh->invitation_key = ecdsa_read_pem_private_key(fp); fclose(fp); - if(!mesh->invitation_key) + + if(!mesh->invitation_key) { logger(mesh, MESHLINK_ERROR, "Reading ECDSA private key file `%s' failed: %s", filename, strerror(errno)); + } } return mesh->invitation_key; @@ -128,16 +137,19 @@ bool node_read_devclass(meshlink_handle_t *mesh, node_t *n) { char *p; init_configuration(&config_tree); - if(!read_host_config(mesh, config_tree, n->name)) + + if(!read_host_config(mesh, config_tree, n->name)) { goto exit; + } if(get_config_string(lookup_config(config_tree, "DeviceClass"), &p)) { n->devclass = atoi(p); free(p); } - if((int)n->devclass < 0 || n->devclass > _DEV_CLASS_MAX) + if((int)n->devclass < 0 || n->devclass > _DEV_CLASS_MAX) { n->devclass = _DEV_CLASS_MAX; + } exit: exit_configuration(&config_tree); @@ -146,8 +158,9 @@ exit: bool node_write_devclass(meshlink_handle_t *mesh, node_t *n) { - if((int)n->devclass < 0 || n->devclass > _DEV_CLASS_MAX) + if((int)n->devclass < 0 || n->devclass > _DEV_CLASS_MAX) { return false; + } bool result = false; @@ -167,8 +180,9 @@ bool node_write_devclass(meshlink_handle_t *mesh, node_t *n) { set_config_int(cnf, n->devclass); - if(!write_host_config(mesh, config_tree, n->name)) + if(!write_host_config(mesh, config_tree, n->name)) { goto fail; + } result = true; @@ -184,18 +198,22 @@ void load_all_nodes(meshlink_handle_t *mesh) { snprintf(dname, PATH_MAX, "%s" SLASH "hosts", mesh->confbase); dir = opendir(dname); + if(!dir) { logger(mesh, MESHLINK_ERROR, "Could not open %s: %s", dname, strerror(errno)); return; } while((ent = readdir(dir))) { - if(!check_id(ent->d_name)) + if(!check_id(ent->d_name)) { continue; + } node_t *n = lookup_node(mesh, ent->d_name); - if(n) + + if(n) { continue; + } n = new_node(); n->name = xstrdup(ent->d_name); @@ -212,8 +230,9 @@ char *get_name(meshlink_handle_t *mesh) { get_config_string(lookup_config(mesh->config, "Name"), &name); - if(!name) + if(!name) { return NULL; + } if(!check_id(name)) { logger(mesh, MESHLINK_ERROR, "Invalid name for mesh->self!"); @@ -243,22 +262,29 @@ static bool add_listen_address(meshlink_handle_t *mesh, char *address, bool bind if(address) { char *space = strchr(address, ' '); + if(space) { *space++ = 0; port = space; } - if(!strcmp(address, "*")) + if(!strcmp(address, "*")) { *address = 0; + } } struct addrinfo *ai, hint = {}; + hint.ai_family = addressfamily; + hint.ai_socktype = SOCK_STREAM; + hint.ai_protocol = IPPROTO_TCP; + hint.ai_flags = AI_PASSIVE; int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai); + free(address); if(err || !ai) { @@ -278,8 +304,9 @@ static bool add_listen_address(meshlink_handle_t *mesh, char *address, bool bind break; } - if(found) + if(found) { continue; + } if(mesh->listen_sockets >= MAXSOCKETS) { logger(mesh, MESHLINK_ERROR, "Too many listening sockets"); @@ -288,8 +315,9 @@ static bool add_listen_address(meshlink_handle_t *mesh, char *address, bool bind int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr); - if(tcp_fd < 0) + if(tcp_fd < 0) { continue; + } int udp_fd = setup_vpn_in_socket(mesh, (sockaddr_t *) aip->ai_addr); @@ -347,16 +375,20 @@ bool setup_myself(meshlink_handle_t *mesh) { mesh->self->options |= PROT_MINOR << 24; - if(!read_ecdsa_private_key(mesh)) + if(!read_ecdsa_private_key(mesh)) { return false; + } /* Ensure mesh->myport is numeric */ if(!atoi(mesh->myport)) { struct addrinfo *ai = str2addrinfo("localhost", mesh->myport, SOCK_DGRAM); sockaddr_t sa; - if(!ai || !ai->ai_addr) + + if(!ai || !ai->ai_addr) { return false; + } + free(mesh->myport); memcpy(&sa, ai->ai_addr, ai->ai_addrlen); sockaddr2str(&sa, NULL, &mesh->myport); @@ -364,8 +396,9 @@ bool setup_myself(meshlink_handle_t *mesh) { /* Check some options */ - if(!setup_myself_reloadable(mesh)) + if(!setup_myself_reloadable(mesh)) { return false; + } /* Compression */ @@ -396,12 +429,17 @@ bool setup_myself(meshlink_handle_t *mesh) { logger(mesh, MESHLINK_INFO, "Could not bind to port %s, asking OS to choose one for us", mesh->myport); free(mesh->myport); mesh->myport = strdup("0"); - if(!mesh->myport) + + if(!mesh->myport) { return false; - if(!add_listen_address(mesh, address, NULL)) + } + + if(!add_listen_address(mesh, address, NULL)) { return false; - } else + } + } else { return false; + } } if(!mesh->listen_sockets) { @@ -429,8 +467,9 @@ bool setup_network(meshlink_handle_t *mesh) { mesh->pingtimeout = 5; maxoutbufsize = 10 * MTU; - if(!setup_myself(mesh)) + if(!setup_myself(mesh)) { return false; + } return true; } @@ -448,8 +487,9 @@ void close_network_connections(meshlink_handle_t *mesh) { } } - if(mesh->outgoings) + if(mesh->outgoings) { list_delete_list(mesh->outgoings); + } if(mesh->self && mesh->self->connection) { terminate_connection(mesh, mesh->self->connection, false); @@ -468,7 +508,9 @@ void close_network_connections(meshlink_handle_t *mesh) { exit_nodes(mesh); exit_connections(mesh); - if(mesh->myport) free(mesh->myport); + if(mesh->myport) { + free(mesh->myport); + } return; } diff --git a/src/net_socket.c b/src/net_socket.c index 97c42fc2..df1bbf13 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -50,13 +50,17 @@ static void configure_tcp(connection_t *c) { #ifdef O_NONBLOCK int flags = fcntl(c->socket, F_GETFL); - if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) + if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) { logger(c->mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + } + #elif defined(WIN32) unsigned long arg = 1; - if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) + if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) { logger(c->mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno)); + } + #endif #if defined(SOL_TCP) && defined(TCP_NODELAY) @@ -74,21 +78,28 @@ static bool bind_to_address(meshlink_handle_t *mesh, connection_t *c) { int s = -1; for(int i = 0; i < mesh->listen_sockets && mesh->listen_socket[i].bindto; i++) { - if(mesh->listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family) + if(mesh->listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family) { continue; - if(s >= 0) + } + + if(s >= 0) { return false; + } + s = i; } - if(s < 0) + if(s < 0) { return false; + } sockaddr_t sa = mesh->listen_socket[s].sa; - if(sa.sa.sa_family == AF_INET) + + if(sa.sa.sa_family == AF_INET) { sa.in.sin_port = 0; - else if(sa.sa.sa_family == AF_INET6) + } else if(sa.sa.sa_family == AF_INET6) { sa.in6.sin6_port = 0; + } if(bind(c->socket, &sa.sa, SALEN(sa.sa))) { logger(mesh, MESHLINK_WARNING, "Can't bind outgoing socket: %s", strerror(errno)); @@ -120,8 +131,11 @@ int setup_listen_socket(const sockaddr_t *sa) { setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option)); #if defined(SOL_IPV6) && defined(IPV6_V6ONLY) - if(sa->sa.sa_family == AF_INET6) + + if(sa->sa.sa_family == AF_INET6) { setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + #endif if(bind(nfd, &sa->sa, SALEN(sa->sa))) { @@ -171,6 +185,7 @@ int setup_vpn_in_socket(meshlink_handle_t *mesh, const sockaddr_t *sa) { #elif defined(WIN32) { unsigned long arg = 1; + if(ioctlsocket(nfd, FIONBIO, &arg) != 0) { closesocket(nfd); logger(mesh, MESHLINK_ERROR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno)); @@ -184,8 +199,11 @@ int setup_vpn_in_socket(meshlink_handle_t *mesh, const sockaddr_t *sa) { setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option)); #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) - if(sa->sa.sa_family == AF_INET6) + + if(sa->sa.sa_family == AF_INET6) { setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + #endif #if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT) @@ -193,29 +211,37 @@ int setup_vpn_in_socket(meshlink_handle_t *mesh, const sockaddr_t *sa) { #endif #if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) + if(mesh->self->options & OPTION_PMTU_DISCOVERY) { option = IP_PMTUDISC_DO; setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option)); } + #elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT) + if(mesh->self->options & OPTION_PMTU_DISCOVERY) { option = 1; setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option)); } + #else #warning No way to disable IPv4 fragmentation #endif #if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) + if(mesh->self->options & OPTION_PMTU_DISCOVERY) { option = IPV6_PMTUDISC_DO; setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option)); } + #elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG) + if(mesh->self->options & OPTION_PMTU_DISCOVERY) { option = 1; setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option)); } + #else #warning No way to disable IPv6 fragmentation #endif @@ -240,8 +266,9 @@ static void retry_outgoing_handler(event_loop_t *loop, void *data) { void retry_outgoing(meshlink_handle_t *mesh, outgoing_t *outgoing) { outgoing->timeout += 5; - if(outgoing->timeout > mesh->maxtimeout) + if(outgoing->timeout > mesh->maxtimeout) { outgoing->timeout = mesh->maxtimeout; + } timeout_add(&mesh->loop, &outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval) { outgoing->timeout, rand() % 100000 @@ -294,10 +321,13 @@ static void do_outgoing_pipe(meshlink_handle_t *mesh, connection_t *c, char *com setenv("NAME", mesh->self->name, true); int result = system(command); - if(result < 0) + + if(result < 0) { logger(mesh, MESHLINK_ERROR, "Could not execute %s: %s", command, strerror(errno)); - else if(result) + } else if(result) { logger(mesh, MESHLINK_ERROR, "%s exited with non-zero status %d", command, result); + } + exit(result); #else logger(mesh, MESHLINK_ERROR, "Proxy type exec not supported on this platform!"); @@ -306,10 +336,12 @@ static void do_outgoing_pipe(meshlink_handle_t *mesh, connection_t *c, char *com } static void handle_meta_write(meshlink_handle_t *mesh, connection_t *c) { - if(c->outbuf.len <= c->outbuf.offset) + if(c->outbuf.len <= c->outbuf.offset) { return; + } ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, MSG_NOSIGNAL); + if(outlen <= 0) { if(!errno || errno == EPIPE) { logger(mesh, MESHLINK_INFO, "Connection closed by %s", c->name); @@ -325,8 +357,10 @@ static void handle_meta_write(meshlink_handle_t *mesh, connection_t *c) { } buffer_read(&c->outbuf, outlen); - if(!c->outbuf.len) + + if(!c->outbuf.len) { io_set(&mesh->loop, &c->io, IO_READ); + } } static void handle_meta_io(event_loop_t *loop, void *data, int flags) { @@ -340,19 +374,20 @@ static void handle_meta_io(event_loop_t *loop, void *data, int flags) { socklen_t len = sizeof(result); getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len); - if(!result) + if(!result) { finish_connecting(mesh, c); - else { + } else { logger(mesh, MESHLINK_DEBUG, "Error while connecting to %s: %s", c->name, sockstrerror(result)); terminate_connection(mesh, c, false); return; } } - if(flags & IO_WRITE) + if(flags & IO_WRITE) { handle_meta_write(mesh, c); - else + } else { handle_meta_connection_data(mesh, c); + } } // Find edges pointing to this node, and use them to build a list of unique, known addresses. @@ -360,18 +395,22 @@ static struct addrinfo *get_known_addresses(node_t *n) { struct addrinfo *ai = NULL; for splay_each(edge_t, e, n->edge_tree) { - if(!e->reverse) + if(!e->reverse) { continue; + } bool found = false; + for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { if(!sockaddrcmp(&e->reverse->address, (sockaddr_t *)aip->ai_addr)) { found = true; break; } } - if(found) + + if(found) { continue; + } // Create a new struct addrinfo, and put it at the head of the list. struct addrinfo *nai = xzalloc(sizeof(*nai) + SALEN(e->reverse->address.sa)); @@ -403,6 +442,7 @@ bool do_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) { int result; begin: + if(!outgoing->ai && !outgoing->nai) { if(!outgoing->cfg) { logger(mesh, MESHLINK_ERROR, "Could not set up a meta connection to %s", outgoing->name); @@ -413,6 +453,7 @@ begin: get_config_string(outgoing->cfg, &address); space = strchr(address, ' '); + if(space) { port = xstrdup(space + 1); *space = 0; @@ -434,12 +475,16 @@ begin: } if(!outgoing->aip) { - if(outgoing->ai) + if(outgoing->ai) { freeaddrinfo(outgoing->ai); + } + outgoing->ai = NULL; - if(outgoing->nai) + if(outgoing->nai) { free_known_addresses(outgoing->nai); + } + outgoing->nai = NULL; goto begin; @@ -458,15 +503,17 @@ begin: if(!mesh->proxytype) { c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); configure_tcp(c); - } else if(mesh->proxytype == PROXY_EXEC) + } else if(mesh->proxytype == PROXY_EXEC) { do_outgoing_pipe(mesh, c, mesh->proxyhost); - else { + } else { proxyai = str2addrinfo(mesh->proxyhost, mesh->proxyport, SOCK_STREAM); + if(!proxyai) { free_connection(c); free(hostname); goto begin; } + logger(mesh, MESHLINK_INFO, "Using proxy at %s port %s", mesh->proxyhost, mesh->proxyport); c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP); configure_tcp(c); @@ -488,8 +535,11 @@ begin: if(mesh->proxytype != PROXY_EXEC) { #if defined(SOL_IPV6) && defined(IPV6_V6ONLY) int option = 1; - if(c->address.sa.sa_family == AF_INET6) + + if(c->address.sa.sa_family == AF_INET6) { setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + #endif bind_to_address(mesh, c); @@ -497,11 +547,11 @@ begin: /* Connect */ - if(!mesh->proxytype) + if(!mesh->proxytype) { result = connect(c->socket, &c->address.sa, SALEN(c->address.sa)); - else if(mesh->proxytype == PROXY_EXEC) + } else if(mesh->proxytype == PROXY_EXEC) { result = 0; - else { + } else { result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen); freeaddrinfo(proxyai); } @@ -546,11 +596,16 @@ void setup_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) { outgoing->cfg = lookup_config(outgoing->config_tree, "Address"); get_config_bool(lookup_config(outgoing->config_tree, "blacklisted"), &blacklisted); - if(blacklisted) return; + + if(blacklisted) { + return; + } if(!outgoing->cfg) { - if(n) + if(n) { outgoing->aip = outgoing->nai = get_known_addresses(n); + } + if(!outgoing->nai) { logger(mesh, MESHLINK_ERROR, "No address known for %s", outgoing->name); return; @@ -601,10 +656,11 @@ void handle_new_meta_connection(event_loop_t *loop, void *data, int flags) { static int samehost_burst; static int samehost_burst_time; - if(mesh->loop.now.tv_sec - samehost_burst_time > samehost_burst) + if(mesh->loop.now.tv_sec - samehost_burst_time > samehost_burst) { samehost_burst = 0; - else + } else { samehost_burst -= mesh->loop.now.tv_sec - samehost_burst_time; + } samehost_burst_time = mesh->loop.now.tv_sec; samehost_burst++; @@ -622,10 +678,11 @@ void handle_new_meta_connection(event_loop_t *loop, void *data, int flags) { static int connection_burst; static int connection_burst_time; - if(mesh->loop.now.tv_sec - connection_burst_time > connection_burst) + if(mesh->loop.now.tv_sec - connection_burst_time > connection_burst) { connection_burst = 0; - else + } else { connection_burst -= mesh->loop.now.tv_sec - connection_burst_time; + } connection_burst_time = mesh->loop.now.tv_sec; connection_burst++; @@ -665,17 +722,21 @@ static void free_outgoing(outgoing_t *outgoing) { timeout_del(&mesh->loop, &outgoing->ev); - if(outgoing->ai) + if(outgoing->ai) { freeaddrinfo(outgoing->ai); + } - if(outgoing->nai) + if(outgoing->nai) { free_known_addresses(outgoing->nai); + } - if(outgoing->config_tree) + if(outgoing->config_tree) { exit_configuration(&outgoing->config_tree); + } - if(outgoing->name) + if(outgoing->name) { free(outgoing->name); + } free(outgoing); } @@ -683,11 +744,12 @@ static void free_outgoing(outgoing_t *outgoing) { void try_outgoing_connections(meshlink_handle_t *mesh) { /* If there is no outgoing list yet, create one. Otherwise, mark all outgoings as deleted. */ - if(!mesh->outgoings) + if(!mesh->outgoings) { mesh->outgoings = list_alloc((list_action_t)free_outgoing); - else { - for list_each(outgoing_t, outgoing, mesh->outgoings) + } else { + for list_each(outgoing_t, outgoing, mesh->outgoings) { outgoing->timeout = -1; + } } /* Make sure there is one outgoing_t in the list for each ConnectTo. */ @@ -737,6 +799,7 @@ void try_outgoing_connections(meshlink_handle_t *mesh) { /* Delete outgoing_ts for which there is no ConnectTo. */ for list_each(outgoing_t, outgoing, mesh->outgoings) - if(outgoing->timeout == -1) + if(outgoing->timeout == -1) { list_delete_node(mesh->outgoings, node); + } } diff --git a/src/netutl.c b/src/netutl.c index 75950f05..f41fbecc 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -80,10 +80,14 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) { int err; if(sa->sa.sa_family == AF_UNKNOWN) { - if(addrstr) + if(addrstr) { *addrstr = xstrdup(sa->unknown.address); - if(portstr) + } + + if(portstr) { *portstr = xstrdup(sa->unknown.port); + } + return; } @@ -96,13 +100,17 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) { scopeid = strchr(address, '%'); - if(scopeid) - *scopeid = '\0'; /* Descope. */ + if(scopeid) { + *scopeid = '\0'; /* Descope. */ + } - if(addrstr) + if(addrstr) { *addrstr = xstrdup(address); - if(portstr) + } + + if(portstr) { *portstr = xstrdup(port); + } } char *sockaddr2hostname(const sockaddr_t *sa) { @@ -118,8 +126,10 @@ char *sockaddr2hostname(const sockaddr_t *sa) { err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV)); - if(err) + + if(err) { logger(NULL, MESHLINK_ERROR, "Error while looking up hostname: %s", err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err)); + } xasprintf(&str, "%s port %s", address, port); @@ -131,8 +141,9 @@ int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b) { result = a->sa.sa_family - b->sa.sa_family; - if(result) + if(result) { return result; + } switch(a->sa.sa_family) { case AF_UNSPEC: @@ -159,8 +170,9 @@ int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) { result = a->sa.sa_family - b->sa.sa_family; - if(result) + if(result) { return result; + } switch(a->sa.sa_family) { case AF_UNSPEC: @@ -169,24 +181,27 @@ int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) { case AF_UNKNOWN: result = strcmp(a->unknown.address, b->unknown.address); - if(result) + if(result) { return result; + } return strcmp(a->unknown.port, b->unknown.port); case AF_INET: result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a)->in.sin_addr); - if(result) + if(result) { return result; + } return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a)->in.sin_port); case AF_INET6: result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a)->in6.sin6_addr); - if(result) + if(result) { return result; + } return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a)->in6.sin6_port); @@ -198,9 +213,9 @@ int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) { } void sockaddrcpy(sockaddr_t *a, const sockaddr_t *b) { - if(b->sa.sa_family != AF_UNKNOWN) + if(b->sa.sa_family != AF_UNKNOWN) { *a = *b; - else { + } else { a->unknown.family = AF_UNKNOWN; a->unknown.address = xstrdup(b->unknown.address); a->unknown.port = xstrdup(b->unknown.port); diff --git a/src/node.c b/src/node.c index 164fdb15..dec86f88 100644 --- a/src/node.c +++ b/src/node.c @@ -39,10 +39,14 @@ void init_nodes(meshlink_handle_t *mesh) { } void exit_nodes(meshlink_handle_t *mesh) { - if(mesh->node_udp_cache) + if(mesh->node_udp_cache) { hash_free(mesh->node_udp_cache); - if(mesh->nodes) + } + + if(mesh->nodes) { splay_delete_tree(mesh->nodes); + } + mesh->node_udp_cache = NULL; mesh->nodes = NULL; } @@ -61,16 +65,18 @@ node_t *new_node(void) { void free_node(node_t *n) { n->status.destroyed = true; - if(n->edge_tree) + if(n->edge_tree) { free_edge_tree(n->edge_tree); + } sockaddrfree(&n->address); ecdsa_free(n->ecdsa); sptps_stop(&n->sptps); - if(n->mtutimeout.cb) + if(n->mtutimeout.cb) { abort(); + } free(n->name); @@ -87,8 +93,9 @@ void node_add(meshlink_handle_t *mesh, node_t *n) { void node_del(meshlink_handle_t *mesh, node_t *n) { timeout_del(&mesh->loop, &n->mtutimeout); - for splay_each(edge_t, e, n->edge_tree) + for splay_each(edge_t, e, n->edge_tree) { edge_del(mesh, e); + } splay_delete(mesh->nodes, n); } @@ -117,6 +124,7 @@ void update_node_udp(meshlink_handle_t *mesh, node_t *n, const sockaddr_t *sa) { if(sa) { n->address = *sa; n->sock = 0; + for(int i = 0; i < mesh->listen_sockets; i++) { if(mesh->listen_socket[i].sa.sa.sa_family == sa->sa.sa_family) { n->sock = i; diff --git a/src/prf.c b/src/prf.c index 526c8706..ec8d0c60 100644 --- a/src/prf.c +++ b/src/prf.c @@ -23,8 +23,9 @@ #include "ed25519/sha512.h" static void memxor(char *buf, char c, size_t len) { - for(size_t i = 0; i < len; i++) + for(size_t i = 0; i < len; i++) { buf[i] ^= c; + } } static const size_t mdlen = 64; @@ -39,29 +40,37 @@ static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t memcpy(tmp, key, keylen); memset(tmp + keylen, 0, mdlen - keylen); } else { - if(sha512(key, keylen, tmp) != 0) + if(sha512(key, keylen, tmp) != 0) { return false; + } } - if(sha512_init(&md) != 0) + if(sha512_init(&md) != 0) { return false; + } // ipad memxor(tmp, 0x36, mdlen); - if(sha512_update(&md, tmp, mdlen) != 0) + + if(sha512_update(&md, tmp, mdlen) != 0) { return false; + } // message - if(sha512_update(&md, msg, msglen) != 0) + if(sha512_update(&md, msg, msglen) != 0) { return false; + } - if(sha512_final(&md, tmp + mdlen) != 0) + if(sha512_final(&md, tmp + mdlen) != 0) { return false; + } // opad memxor(tmp, 0x36 ^ 0x5c, mdlen); - if(sha512(tmp, sizeof(tmp), out) != 0) + + if(sha512(tmp, sizeof(tmp), out) != 0) { return false; + } return true; } @@ -83,18 +92,23 @@ bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char while(outlen > 0) { /* Inner HMAC */ - if(!hmac_sha512(data, sizeof(data), secret, secretlen, data)) + if(!hmac_sha512(data, sizeof(data), secret, secretlen, data)) { return false; + } /* Outer HMAC */ if(outlen >= mdlen) { - if(!hmac_sha512(data, sizeof(data), secret, secretlen, out)) + if(!hmac_sha512(data, sizeof(data), secret, secretlen, out)) { return false; + } + out += mdlen; outlen -= mdlen; } else { - if(!hmac_sha512(data, sizeof(data), secret, secretlen, hash)) + if(!hmac_sha512(data, sizeof(data), secret, secretlen, hash)) { return false; + } + memcpy(out, hash, outlen); out += outlen; outlen = 0; diff --git a/src/protocol.c b/src/protocol.c index 08226f67..e0a0dbb2 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -50,12 +50,14 @@ static char (*request_name[]) = { }; bool check_id(const char *id) { - if(!id || !*id) + if(!id || !*id) { return false; + } for(; *id; id++) - if(!isalnum(*id) && *id != '_' && *id != '-') + if(!isalnum(*id) && *id != '_' && *id != '-') { return false; + } return true; } @@ -88,8 +90,9 @@ bool send_request(meshlink_handle_t *mesh, connection_t *c, const char *format, if(c == mesh->everyone) { broadcast_meta(mesh, NULL, request, len); return true; - } else + } else { return send_meta(mesh, c, request, len); + } } void forward_request(meshlink_handle_t *mesh, connection_t *from, const char *request) { @@ -105,8 +108,10 @@ void forward_request(meshlink_handle_t *mesh, connection_t *from, const char *re bool receive_request(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(c->outgoing && mesh->proxytype == PROXY_HTTP && c->allow_request == ID) { - if(!request[0] || request[0] == '\r') + if(!request[0] || request[0] == '\r') { return true; + } + if(!strncasecmp(request, "HTTP/1.1 ", 9)) { if(!strncmp(request + 9, "200", 3)) { logger(mesh, MESHLINK_DEBUG, "Proxy request granted"); @@ -124,8 +129,9 @@ bool receive_request(meshlink_handle_t *mesh, connection_t *c, const char *reque if((reqno < 0) || (reqno >= LAST) || !request_handlers[reqno]) { logger(mesh, MESHLINK_DEBUG, "Unknown request from %s: %s", c->name, request); return false; - } else + } else { logger(mesh, MESHLINK_DEBUG, "Got %s from %s: %s", request_name[reqno], c->name, request); + } if((c->allow_request != ALL) && (c->allow_request != reqno)) { logger(mesh, MESHLINK_ERROR, "Unauthorized request from %s", c->name); @@ -151,8 +157,9 @@ static int past_request_compare(const past_request_t *a, const past_request_t *b } static void free_past_request(past_request_t *r) { - if(r->request) + if(r->request) { free((void *)r->request); + } free(r); } @@ -163,14 +170,16 @@ static void age_past_requests(event_loop_t *loop, void *data) { int left = 0, deleted = 0; for splay_each(past_request_t, p, mesh->past_request_tree) { - if(p->firstseen + mesh->pinginterval <= mesh->loop.now.tv_sec) + if(p->firstseen + mesh->pinginterval <= mesh->loop.now.tv_sec) { splay_delete_node(mesh->past_request_tree, node), deleted++; - else + } else { left++; + } } - if(left || deleted) + if(left || deleted) { logger(mesh, MESHLINK_DEBUG, "Aging past requests: deleted %d, left %d", deleted, left); + } if(left) timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timeval) { @@ -203,8 +212,10 @@ void init_requests(meshlink_handle_t *mesh) { } void exit_requests(meshlink_handle_t *mesh) { - if(mesh->past_request_tree) + if(mesh->past_request_tree) { splay_delete_tree(mesh->past_request_tree); + } + mesh->past_request_tree = NULL; timeout_del(&mesh->loop, &mesh->past_request_timeout); diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 69507b77..610cbaf8 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -53,31 +53,41 @@ static bool send_proxyrequest(meshlink_handle_t *mesh, connection_t *c) { free(port); return true; } + case PROXY_SOCKS4: { if(c->address.sa.sa_family != AF_INET) { logger(mesh, MESHLINK_ERROR, "Cannot connect to an IPv6 host through a SOCKS 4 proxy!"); return false; } + char s4req[9 + (mesh->proxyuser ? strlen(mesh->proxyuser) : 0)]; s4req[0] = 4; s4req[1] = 1; memcpy(s4req + 2, &c->address.in.sin_port, 2); memcpy(s4req + 4, &c->address.in.sin_addr, 4); - if(mesh->proxyuser) + + if(mesh->proxyuser) { memcpy(s4req + 8, mesh->proxyuser, strlen(mesh->proxyuser)); + } + s4req[sizeof(s4req) - 1] = 0; c->tcplen = 8; return send_meta(mesh, c, s4req, sizeof(s4req)); } + case PROXY_SOCKS5: { int len = 3 + 6 + (c->address.sa.sa_family == AF_INET ? 4 : 16); c->tcplen = 2; - if(mesh->proxypass) + + if(mesh->proxypass) { len += 3 + strlen(mesh->proxyuser) + strlen(mesh->proxypass); + } + char s5req[len]; int i = 0; s5req[i++] = 5; s5req[i++] = 1; + if(mesh->proxypass) { s5req[i++] = 2; s5req[i++] = 1; @@ -88,11 +98,14 @@ static bool send_proxyrequest(meshlink_handle_t *mesh, connection_t *c) { memcpy(s5req + i, mesh->proxypass, strlen(mesh->proxypass)); i += strlen(mesh->proxypass); c->tcplen += 2; - } else + } else { s5req[i++] = 0; + } + s5req[i++] = 5; s5req[i++] = 1; s5req[i++] = 0; + if(c->address.sa.sa_family == AF_INET) { s5req[i++] = 1; memcpy(s5req + i, &c->address.in.sin_addr, 4); @@ -111,15 +124,21 @@ static bool send_proxyrequest(meshlink_handle_t *mesh, connection_t *c) { logger(mesh, MESHLINK_ERROR, "Address family %hx not supported for SOCKS 5 proxies!", c->address.sa.sa_family); return false; } - if(i > len) + + if(i > len) { abort(); + } + return send_meta(mesh, c, s5req, sizeof(s5req)); } + case PROXY_SOCKS4A: logger(mesh, MESHLINK_ERROR, "Proxy type not implemented yet"); return false; + case PROXY_EXEC: return true; + default: logger(mesh, MESHLINK_ERROR, "Unknown proxy type"); return false; @@ -131,14 +150,16 @@ bool send_id(meshlink_handle_t *mesh, connection_t *c) { int minor = mesh->self->connection->protocol_minor; if(mesh->proxytype && c->outgoing) - if(!send_proxyrequest(mesh, c)) + if(!send_proxyrequest(mesh, c)) { return false; + } return send_request(mesh, c, "%d %s %d.%d", ID, mesh->self->connection->name, mesh->self->connection->protocol_major, minor); } static bool finalize_invitation(meshlink_handle_t *mesh, connection_t *c, const void *data, uint16_t len) { (void)len; + if(strchr(data, '\n')) { logger(mesh, MESHLINK_ERROR, "Received invalid key from invited node %s!\n", c->name); return false; @@ -147,12 +168,14 @@ static bool finalize_invitation(meshlink_handle_t *mesh, connection_t *c, const // Create a new host config file char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, c->name); + if(!access(filename, F_OK)) { logger(mesh, MESHLINK_ERROR, "Host config file for %s already exists!\n", c->name); return false; } FILE *f = fopen(filename, "w"); + if(!f) { logger(mesh, MESHLINK_ERROR, "Error trying to create %s: %s\n", filename, strerror(errno)); return false; @@ -176,14 +199,17 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat connection_t *c = handle; meshlink_handle_t *mesh = c->mesh; - if(type == 128) + if(type == 128) { return true; + } - if(type == 1 && c->status.invitation_used) + if(type == 1 && c->status.invitation_used) { return finalize_invitation(mesh, c, data, len); + } - if(type != 0 || len != 18 || c->status.invitation_used) + if(type != 0 || len != 18 || c->status.invitation_used) { return false; + } // Recover the filename from the cookie and the key char *fingerprint = ecdsa_get_base64_public_key(mesh->invitation_key); @@ -202,15 +228,18 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat // Atomically rename the invitation file if(rename(filename, usedname)) { - if(errno == ENOENT) + if(errno == ENOENT) { logger(mesh, MESHLINK_ERROR, "Peer %s tried to use non-existing invitation %s\n", c->name, cookie); - else + } else { logger(mesh, MESHLINK_ERROR, "Error trying to rename invitation %s\n", cookie); + } + return false; } // Open the renamed file FILE *f = fopen(usedname, "r"); + if(!f) { logger(mesh, MESHLINK_ERROR, "Error trying to open invitation %s\n", cookie); return false; @@ -219,16 +248,20 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat // Read the new node's Name from the file char buf[1024]; fgets(buf, sizeof(buf), f); - if(*buf) + + if(*buf) { buf[strlen(buf) - 1] = 0; + } len = strcspn(buf, " \t="); char *name = buf + len; name += strspn(name, " \t"); + if(*name == '=') { name++; name += strspn(name, " \t"); } + buf[len] = 0; if(!*buf || !*name || strcasecmp(buf, "Name") || !check_id(name)) { @@ -243,8 +276,11 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat // Send the node the contents of the invitation file rewind(f); size_t result; - while((result = fread(buf, 1, sizeof(buf), f))) + + while((result = fread(buf, 1, sizeof(buf), f))) { sptps_send_record(&c->sptps, 0, buf, result); + } + sptps_send_record(&c->sptps, 1, buf, 0); fclose(f); unlink(usedname); @@ -272,6 +308,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { } c->ecdsa = ecdsa_set_base64_public_key(name + 1); + if(!c->ecdsa) { logger(mesh, MESHLINK_ERROR, "Got bad invitation from %s", c->name); return false; @@ -279,10 +316,15 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { c->status.invitation = true; char *mykey = ecdsa_get_base64_public_key(mesh->invitation_key); - if(!mykey) + + if(!mykey) { return false; - if(!send_request(mesh, c, "%d %s", ACK, mykey)) + } + + if(!send_request(mesh, c, "%d %s", ACK, mykey)) { return false; + } + free(mykey); c->protocol_minor = 2; @@ -306,8 +348,10 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { return false; } } else { - if(c->name) + if(c->name) { free(c->name); + } + c->name = xstrdup(name); } @@ -334,6 +378,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { logger(mesh, MESHLINK_ERROR, "No key known for peer %s", c->name); node_t *n = lookup_node(mesh, c->name); + if(n && !n->status.waitingforkey) { logger(mesh, MESHLINK_INFO, "Requesting key from peer %s", c->name); send_req_key(mesh, n); @@ -353,10 +398,11 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { c->allow_request = ACK; char label[sizeof(meshlink_tcp_label) + strlen(mesh->self->name) + strlen(c->name) + 2]; - if(c->outgoing) + if(c->outgoing) { snprintf(label, sizeof(label), "%s %s %s", meshlink_tcp_label, mesh->self->name, c->name); - else + } else { snprintf(label, sizeof(label), "%s %s %s", meshlink_tcp_label, c->name, mesh->self->name); + } return sptps_start(&c->sptps, c, c->outgoing, false, mesh->self->connection->ecdsa, c->ecdsa, label, sizeof(label) - 1, send_meta_sptps, receive_meta_sptps); } @@ -365,8 +411,9 @@ bool send_ack(meshlink_handle_t *mesh, connection_t *c) { /* Check some options */ - if(mesh->self->options & OPTION_PMTU_DISCOVERY) + if(mesh->self->options & OPTION_PMTU_DISCOVERY) { c->options |= OPTION_PMTU_DISCOVERY; + } return send_request(mesh, c, "%d %s %d %x", ACK, mesh->myport, mesh->devclass, (c->options & 0xffffff) | (PROT_MINOR << 24)); } @@ -375,8 +422,9 @@ static void send_everything(meshlink_handle_t *mesh, connection_t *c) { /* Send all known subnets and edges */ for splay_each(node_t, n, mesh->nodes) { - for splay_each(edge_t, e, n->edge_tree) + for splay_each(edge_t, e, n->edge_tree) { send_add_edge(mesh, c, e); + } } } @@ -411,10 +459,11 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { logger(mesh, MESHLINK_DEBUG, "Established a second connection with %s, closing old connection", n->connection->name); if(n->connection->outgoing) { - if(c->outgoing) + if(c->outgoing) { logger(mesh, MESHLINK_WARNING, "Two outgoing connections to the same node!"); - else + } else { c->outgoing = n->connection->outgoing; + } n->connection->outgoing = NULL; } @@ -432,10 +481,12 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { n->connection = c; c->node = n; + if(!(c->options & options & OPTION_PMTU_DISCOVERY)) { c->options &= ~OPTION_PMTU_DISCOVERY; options &= ~OPTION_PMTU_DISCOVERY; } + c->options |= options; /* Activate this connection */ diff --git a/src/protocol_edge.c b/src/protocol_edge.c index c18319e0..40172b9d 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -88,8 +88,9 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { return false; } - if(seen_request(mesh, request)) + if(seen_request(mesh, request)) { return true; + } /* Lookup nodes */ @@ -137,8 +138,9 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { edge_del(mesh, e); graph(mesh); } - } else + } else { return true; + } } else if(from == mesh->self) { logger(mesh, MESHLINK_WARNING, "Got %s from %s for ourself which does not exist", "ADD_EDGE", c->name); @@ -193,8 +195,9 @@ bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { return false; } - if(seen_request(mesh, request)) + if(seen_request(mesh, request)) { return true; + } /* Lookup nodes */ @@ -247,6 +250,7 @@ bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!to->status.reachable) { e = lookup_edge(to, mesh->self); + if(e) { send_del_edge(mesh, mesh->everyone, e); edge_del(mesh, e); diff --git a/src/protocol_key.c b/src/protocol_key.c index 5f1be34e..cae95047 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -37,8 +37,9 @@ void send_key_changed(meshlink_handle_t *mesh) { /* Force key exchange for connections using SPTPS */ for splay_each(node_t, n, mesh->nodes) - if(n->status.reachable && n->status.validkey) + if(n->status.reachable && n->status.validkey) { sptps_force_kex(&n->sptps); + } } bool key_changed_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { @@ -50,8 +51,9 @@ bool key_changed_h(meshlink_handle_t *mesh, connection_t *c, const char *request return false; } - if(seen_request(mesh, request)) + if(seen_request(mesh, request)) { return true; + } n = lookup_node(mesh, name); @@ -84,8 +86,9 @@ bool send_req_key(meshlink_handle_t *mesh, node_t *to) { return true; } - if(to->sptps.label) + if(to->sptps.label) { logger(mesh, MESHLINK_DEBUG, "send_req_key(%s) called while sptps->label != NULL!", to->name); + } char label[sizeof(meshlink_udp_label) + strlen(mesh->self->name) + strlen(to->name) + 2]; snprintf(label, sizeof(label), "%s %s %s", meshlink_udp_label, mesh->self->name, to->name); @@ -101,6 +104,7 @@ bool send_req_key(meshlink_handle_t *mesh, node_t *to) { static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char *request, node_t *from, int reqno) { (void)c; + switch(reqno) { case REQ_PUBKEY: { char *pubkey = ecdsa_get_base64_public_key(mesh->self->connection->ecdsa); @@ -116,6 +120,7 @@ static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char * } char pubkey[MAX_STRING_SIZE]; + if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "ANS_PUBKEY", from->name, "invalid pubkey"); return true; @@ -135,6 +140,7 @@ static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char * if(from->sptps.label) { logger(mesh, MESHLINK_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name); + if(strcmp(mesh->self->name, from->name) < 0) { logger(mesh, MESHLINK_DEBUG, "Ignoring REQ_KEY from %s.", from->name); return true; @@ -168,10 +174,12 @@ static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char * char buf[MAX_STRING_SIZE]; int len; + if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "REQ_SPTPS", from->name, "invalid SPTPS data"); return true; } + sptps_receive_data(&from->sptps, buf, len); return true; } @@ -218,8 +226,9 @@ bool req_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(to == mesh->self) { /* Yes */ /* Is this an extended REQ_KEY message? */ - if(reqno) + if(reqno) { return req_key_ext_h(mesh, c, request, from, reqno); + } /* This should never happen. Ignore it, unless it came directly from the connected peer, in which case we disconnect. */ return from->connection != c; @@ -317,8 +326,9 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { char buf[strlen(key)]; int len = b64decode(key, buf, strlen(key)); - if(!len || !sptps_receive_data(&from->sptps, buf, len)) + if(!len || !sptps_receive_data(&from->sptps, buf, len)) { logger(mesh, MESHLINK_ERROR, "Error processing SPTPS data from %s", from->name); + } if(from->status.validkey) { if(*address && *port) { @@ -327,8 +337,9 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { update_node_udp(mesh, from, &sa); } - if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY)) + if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY)) { send_mtu_probe(mesh, from); + } } return true; diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 5ec01d92..727881bd 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -94,8 +94,11 @@ bool pong_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(c->outgoing) { c->outgoing->timeout = 0; c->outgoing->cfg = NULL; - if(c->outgoing->ai) + + if(c->outgoing->ai) { freeaddrinfo(c->outgoing->ai); + } + c->outgoing->ai = NULL; c->outgoing->aip = NULL; } diff --git a/src/route.c b/src/route.c index 00d3d142..f7a728dc 100644 --- a/src/route.c +++ b/src/route.c @@ -31,8 +31,9 @@ static bool checklength(node_t *source, vpn_packet_t *packet, uint16_t length) { if(packet->len < length) { logger(source->mesh, MESHLINK_WARNING, "Got too short packet from %s", source->name); return false; - } else + } else { return true; + } } void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) { @@ -45,8 +46,9 @@ void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) { logger(mesh, MESHLINK_DEBUG, "Routing packet from \"%s\" to \"%s\"\n", hdr->source, hdr->destination); //Check Lenght - if(!checklength(source, packet, sizeof(*hdr))) + if(!checklength(source, packet, sizeof(*hdr))) { return; + } if(owner == NULL) { //Lookup failed @@ -60,12 +62,17 @@ void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) { size_t len = packet->len - sizeof(*hdr); char hex[len * 2 + 1]; - if(mesh->log_level >= MESHLINK_DEBUG) - bin2hex(payload, hex, len); // don't do this unless it's going to be logged + + if(mesh->log_level >= MESHLINK_DEBUG) { + bin2hex(payload, hex, len); // don't do this unless it's going to be logged + } + logger(mesh, MESHLINK_DEBUG, "I received a packet for me with payload: %s\n", hex); - if(mesh->receive_cb) + if(mesh->receive_cb) { mesh->receive_cb(mesh, (meshlink_node_t *)source, payload, len); + } + return; } @@ -76,6 +83,7 @@ void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) { } via = (owner->via == mesh->self) ? owner->nexthop : owner->via; + if(via == source) { logger(mesh, MESHLINK_ERROR, "Routing loop for packet from %s!", source->name); return; diff --git a/src/splay_tree.c b/src/splay_tree.c index b9130d6b..006b4d5e 100644 --- a/src/splay_tree.c +++ b/src/splay_tree.c @@ -31,8 +31,10 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r int c; if(!root) { - if(result) + if(result) { *result = 0; + } + return NULL; } @@ -45,8 +47,9 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r child->parent = rightbottom; rightbottom = child; - if((root->left = child->right)) + if((root->left = child->right)) { child->right->parent = root; + } child->right = root; root->parent = child; @@ -89,8 +92,9 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r child->parent = leftbottom; leftbottom = child; - if((root->right = child->left)) + if((root->right = child->left)) { child->left->parent = root; + } child->left = root; root->parent = child; @@ -125,8 +129,9 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r root = child; break; } - } else + } else { break; + } } /* Merge trees */ @@ -136,6 +141,7 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r leftbottom->right = root->left; root->left->parent = leftbottom; } + root->left = left.right; left.right->parent = root; } @@ -145,6 +151,7 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r rightbottom->left = root->right; root->right->parent = rightbottom; } + root->right = right.left; right.left->parent = root; } @@ -152,8 +159,10 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r /* Return result */ tree->root = root; - if(result) + + if(result) { *result = c; + } return tree->root; } @@ -164,12 +173,16 @@ static void splay_bottom_up(splay_tree_t *tree, splay_node_t *node) { while((parent = node->parent)) { if(!(grandparent = parent->parent)) { /* zig */ if(node == parent->left) { - if((parent->left = node->right)) + if((parent->left = node->right)) { parent->left->parent = parent; + } + node->right = parent; } else { - if((parent->right = node->left)) + if((parent->right = node->left)) { parent->right->parent = parent; + } + node->left = parent; } @@ -179,52 +192,69 @@ static void splay_bottom_up(splay_tree_t *tree, splay_node_t *node) { greatgrandparent = grandparent->parent; if(node == parent->left && parent == grandparent->left) { /* left zig-zig */ - if((grandparent->left = parent->right)) + if((grandparent->left = parent->right)) { grandparent->left->parent = grandparent; + } + parent->right = grandparent; grandparent->parent = parent; - if((parent->left = node->right)) + if((parent->left = node->right)) { parent->left->parent = parent; + } + node->right = parent; parent->parent = node; } else if(node == parent->right && parent == grandparent->right) { /* right zig-zig */ - if((grandparent->right = parent->left)) + if((grandparent->right = parent->left)) { grandparent->right->parent = grandparent; + } + parent->left = grandparent; grandparent->parent = parent; - if((parent->right = node->left)) + if((parent->right = node->left)) { parent->right->parent = parent; + } + node->left = parent; parent->parent = node; } else if(node == parent->right && parent == grandparent->left) { /* left-right zig-zag */ - if((parent->right = node->left)) + if((parent->right = node->left)) { parent->right->parent = parent; + } + node->left = parent; parent->parent = node; - if((grandparent->left = node->right)) + if((grandparent->left = node->right)) { grandparent->left->parent = grandparent; + } + node->right = grandparent; grandparent->parent = node; } else { /* right-left zig-zag */ - if((parent->left = node->right)) + if((parent->left = node->right)) { parent->left->parent = parent; + } + node->right = parent; parent->parent = node; - if((grandparent->right = node->left)) + if((grandparent->right = node->left)) { grandparent->right->parent = grandparent; + } + node->left = grandparent; grandparent->parent = node; } if((node->parent = greatgrandparent)) { - if(grandparent == greatgrandparent->left) + if(grandparent == greatgrandparent->left) { greatgrandparent->left = node; - else + } else { greatgrandparent->right = node; + } } } } @@ -253,8 +283,9 @@ splay_node_t *splay_alloc_node(void) { } void splay_free_node(splay_tree_t *tree, splay_node_t *node) { - if(node->data && tree->delete) + if(node->data && tree->delete) { tree->delete(node->data); + } free(node); } @@ -309,8 +340,10 @@ splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *tree, const node = tree->root; if(!node) { - if(result) + if(result) { *result = 0; + } + return NULL; } @@ -318,21 +351,26 @@ splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *tree, const c = tree->compare(data, node->data); if(c < 0) { - if(node->left) + if(node->left) { node = node->left; - else + } else { break; + } } else if(c > 0) { - if(node->right) + if(node->right) { node = node->right; - else + } else { break; - } else + } + } else { break; + } } - if(result) + if(result) { *result = c; + } + return node; } @@ -346,8 +384,9 @@ splay_node_t *splay_search_closest_smaller_node(splay_tree_t *tree, const void * node = splay_search_closest_node(tree, data, &result); - if(result < 0) + if(result < 0) { node = node->prev; + } return node; } @@ -358,8 +397,9 @@ splay_node_t *splay_search_closest_greater_node(splay_tree_t *tree, const void * node = splay_search_closest_node(tree, data, &result); - if(result > 0) + if(result > 0) { node = node->next; + } return node; } @@ -377,16 +417,18 @@ splay_node_t *splay_insert(splay_tree_t *tree, void *data) { } else { closest = splay_search_closest_node(tree, data, &result); - if(!result) + if(!result) { return NULL; + } new = splay_alloc_node(); new->data = data; - if(result < 0) + if(result < 0) { splay_insert_before(tree, closest, new); - else + } else { splay_insert_after(tree, closest, new); + } } return new; @@ -398,18 +440,20 @@ splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) { node->left = node->right = node->parent = node->next = node->prev = NULL; - if(!tree->root) + if(!tree->root) { splay_insert_top(tree, node); - else { + } else { closest = splay_search_closest_node(tree, node->data, &result); - if(!result) + if(!result) { return NULL; + } - if(result < 0) + if(result < 0) { splay_insert_before(tree, closest, node); - else + } else { splay_insert_after(tree, closest, node); + } } return node; @@ -423,26 +467,34 @@ void splay_insert_top(splay_tree_t *tree, splay_node_t *node) { void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t *node) { if(!before) { - if(tree->tail) + if(tree->tail) { splay_insert_after(tree, tree->tail, node); - else + } else { splay_insert_top(tree, node); + } + return; } node->next = before; - if((node->prev = before->prev)) + + if((node->prev = before->prev)) { before->prev->next = node; - else + } else { tree->head = node; + } + before->prev = node; splay_bottom_up(tree, before); node->right = before; before->parent = node; - if((node->left = before->left)) + + if((node->left = before->left)) { before->left->parent = node; + } + before->left = NULL; node->parent = NULL; @@ -452,26 +504,34 @@ void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *node) { if(!after) { - if(tree->head) + if(tree->head) { splay_insert_before(tree, tree->head, node); - else + } else { splay_insert_top(tree, node); + } + return; } node->prev = after; - if((node->next = after->next)) + + if((node->next = after->next)) { after->next->prev = node; - else + } else { tree->tail = node; + } + after->next = node; splay_bottom_up(tree, after); node->left = after; after->parent = node; - if((node->right = after->right)) + + if((node->right = after->right)) { after->right->parent = node; + } + after->right = NULL; node->parent = NULL; @@ -484,35 +544,41 @@ splay_node_t *splay_unlink(splay_tree_t *tree, void *data) { node = splay_search_node(tree, data); - if(node) + if(node) { splay_unlink_node(tree, node); + } return node; } void splay_unlink_node(splay_tree_t *tree, splay_node_t *node) { - if(node->prev) + if(node->prev) { node->prev->next = node->next; - else + } else { tree->head = node->next; + } - if(node->next) + if(node->next) { node->next->prev = node->prev; - else + } else { tree->tail = node->prev; + } splay_bottom_up(tree, node); if(node->prev) { node->left->parent = NULL; tree->root = node->left; - if((node->prev->right = node->right)) + + if((node->prev->right = node->right)) { node->right->parent = node->prev; + } } else if(node->next) { tree->root = node->right; node->right->parent = NULL; - } else + } else { tree->root = NULL; + } tree->count--; } @@ -527,8 +593,9 @@ void splay_delete(splay_tree_t *tree, void *data) { node = splay_search_node(tree, data); - if(node) + if(node) { splay_delete_node(tree, node); + } } /* Fast tree cleanup */ diff --git a/src/sptps.c b/src/sptps.c index 01fb438f..3bc811ed 100644 --- a/src/sptps.c +++ b/src/sptps.c @@ -108,8 +108,9 @@ static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data } // Send a record (private version, accepts all record types, handles encryption and authentication). static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_t len) { - if(s->datagram) + if(s->datagram) { return send_record_priv_datagram(s, type, data, len); + } char buffer[len + 19UL]; @@ -135,11 +136,13 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_ bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len) { // Sanity checks: application cannot send data before handshake is finished, // and only record types 0..127 are allowed. - if(!s->outstate) + if(!s->outstate) { return error(s, EINVAL, "Handshake phase not finished yet"); + } - if(type >= SPTPS_HANDSHAKE) + if(type >= SPTPS_HANDSHAKE) { return error(s, EINVAL, "Invalid application record type"); + } return send_record_priv(s, type, data, len); } @@ -149,11 +152,15 @@ static bool send_kex(sptps_t *s) { size_t keylen = ECDH_SIZE; // Make room for our KEX message, which we will keep around since send_sig() needs it. - if(s->mykex) + if(s->mykex) { return false; + } + s->mykex = realloc(s->mykex, 1 + 32 + keylen); - if(!s->mykex) + + if(!s->mykex) { return error(s, errno, strerror(errno)); + } // Set version byte to zero. s->mykex[0] = SPTPS_VERSION; @@ -162,8 +169,9 @@ static bool send_kex(sptps_t *s) { randomize(s->mykex + 1, 32); // Create a new ECDH public key. - if(!(s->ecdh = ecdh_generate_public(s->mykex + 1 + 32))) + if(!(s->ecdh = ecdh_generate_public(s->mykex + 1 + 32))) { return error(s, EINVAL, "Failed to generate ECDH public key"); + } return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 1 + 32 + keylen); } @@ -183,8 +191,9 @@ static bool send_sig(sptps_t *s) { memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen); // Sign the result. - if(!ecdsa_sign(s->mykey, msg, sizeof(msg), sig)) + if(!ecdsa_sign(s->mykey, msg, sizeof(msg), sig)) { return error(s, EINVAL, "Failed to sign SIG record"); + } // Send the SIG exchange record. return send_record_priv(s, SPTPS_HANDSHAKE, sig, sizeof(sig)); @@ -196,20 +205,25 @@ static bool generate_key_material(sptps_t *s, const char *shared, size_t len) { if(!s->outstate) { s->incipher = chacha_poly1305_init(); s->outcipher = chacha_poly1305_init(); - if(!s->incipher || !s->outcipher) + + if(!s->incipher || !s->outcipher) { return error(s, EINVAL, "Failed to open cipher"); + } } // Allocate memory for key material size_t keylen = 2 * CHACHA_POLY1305_KEYLEN; s->key = realloc(s->key, keylen); - if(!s->key) + + if(!s->key) { return error(s, errno, strerror(errno)); + } // Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce char seed[s->labellen + 64 + 13]; strcpy(seed, "key expansion"); + if(s->initiator) { memcpy(seed + 13, s->mykex + 1, 32); memcpy(seed + 45, s->hiskex + 1, 32); @@ -217,11 +231,13 @@ static bool generate_key_material(sptps_t *s, const char *shared, size_t len) { memcpy(seed + 13, s->hiskex + 1, 32); memcpy(seed + 45, s->mykex + 1, 32); } + memcpy(seed + 77, s->label, s->labellen); // Use PRF to generate the key material - if(!prf(shared, len, seed, s->labellen + 64 + 13, s->key, keylen)) + if(!prf(shared, len, seed, s->labellen + 64 + 13, s->key, keylen)) { return error(s, EINVAL, "Failed to generate key material"); + } return true; } @@ -234,15 +250,19 @@ static bool send_ack(sptps_t *s) { // Receive an ACKnowledgement record. static bool receive_ack(sptps_t *s, const char *data, uint16_t len) { (void)data; - if(len) + + if(len) { return error(s, EIO, "Invalid ACK record length"); + } if(s->initiator) { - if(!chacha_poly1305_set_key(s->incipher, s->key)) + if(!chacha_poly1305_set_key(s->incipher, s->key)) { return error(s, EINVAL, "Failed to set counter"); + } } else { - if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN)) + if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN)) { return error(s, EINVAL, "Failed to set counter"); + } } free(s->key); @@ -255,17 +275,22 @@ static bool receive_ack(sptps_t *s, const char *data, uint16_t len) { // Receive a Key EXchange record, respond by sending a SIG record. static bool receive_kex(sptps_t *s, const char *data, uint16_t len) { // Verify length of the HELLO record - if(len != 1 + 32 + ECDH_SIZE) + if(len != 1 + 32 + ECDH_SIZE) { return error(s, EIO, "Invalid KEX record length"); + } // Ignore version number for now. // Make a copy of the KEX message, send_sig() and receive_sig() need it - if(s->hiskex) + if(s->hiskex) { return error(s, EINVAL, "Received a second KEX message before first has been processed"); + } + s->hiskex = realloc(s->hiskex, len); - if(!s->hiskex) + + if(!s->hiskex) { return error(s, errno, strerror(errno)); + } memcpy(s->hiskex, data, len); @@ -278,8 +303,9 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) { size_t siglen = ecdsa_size(s->hiskey); // Verify length of KEX record. - if(len != siglen) + if(len != siglen) { return error(s, EIO, "Invalid KEX record length"); + } // Concatenate both KEX messages, plus tag indicating if it is from the connection originator char msg[(1 + 32 + keylen) * 2 + 1 + s->labellen]; @@ -290,18 +316,23 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) { memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen); // Verify signature. - if(!ecdsa_verify(s->hiskey, msg, sizeof(msg), data)) + if(!ecdsa_verify(s->hiskey, msg, sizeof(msg), data)) { return error(s, EIO, "Failed to verify SIG record"); + } // Compute shared secret. char shared[ECDH_SHARED_SIZE]; - if(!ecdh_compute_shared(s->ecdh, s->hiskex + 1 + 32, shared)) + + if(!ecdh_compute_shared(s->ecdh, s->hiskex + 1 + 32, shared)) { return error(s, EINVAL, "Failed to compute ECDH shared secret"); + } + s->ecdh = NULL; // Generate key material from shared secret. - if(!generate_key_material(s, shared, sizeof(shared))) + if(!generate_key_material(s, shared, sizeof(shared))) { return false; + } free(s->mykex); free(s->hiskex); @@ -310,16 +341,19 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) { s->hiskex = NULL; // Send cipher change record - if(s->outstate && !send_ack(s)) + if(s->outstate && !send_ack(s)) { return false; + } // TODO: only set new keys after ACK has been set/received if(s->initiator) { - if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN)) + if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN)) { return error(s, EINVAL, "Failed to set key"); + } } else { - if(!chacha_poly1305_set_key(s->outcipher, s->key)) + if(!chacha_poly1305_set_key(s->outcipher, s->key)) { return error(s, EINVAL, "Failed to set key"); + } } return true; @@ -327,8 +361,9 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) { // Force another Key EXchange (for testing purposes). bool sptps_force_kex(sptps_t *s) { - if(!s->outstate || s->state != SPTPS_SECONDARY_KEX) + if(!s->outstate || s->state != SPTPS_SECONDARY_KEX) { return error(s, EINVAL, "Cannot force KEX in current state"); + } s->state = SPTPS_KEX; return send_kex(s); @@ -339,38 +374,56 @@ static bool receive_handshake(sptps_t *s, const char *data, uint16_t len) { // Only a few states to deal with handshaking. switch(s->state) { case SPTPS_SECONDARY_KEX: + // We receive a secondary KEX request, first respond by sending our own. - if(!send_kex(s)) + if(!send_kex(s)) { return false; - // fallthrough + } + + // fallthrough case SPTPS_KEX: + // We have sent our KEX request, we expect our peer to sent one as well. - if(!receive_kex(s, data, len)) + if(!receive_kex(s, data, len)) { return false; + } + s->state = SPTPS_SIG; return true; + case SPTPS_SIG: + // If we already sent our secondary public ECDH key, we expect the peer to send his. - if(!receive_sig(s, data, len)) + if(!receive_sig(s, data, len)) { return false; - if(s->outstate) + } + + if(s->outstate) { s->state = SPTPS_ACK; - else { + } else { s->outstate = true; - if(!receive_ack(s, NULL, 0)) + + if(!receive_ack(s, NULL, 0)) { return false; + } + s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); s->state = SPTPS_SECONDARY_KEX; } return true; + case SPTPS_ACK: + // We expect a handshake message to indicate transition to the new keys. - if(!receive_ack(s, data, len)) + if(!receive_ack(s, data, len)) { return false; + } + s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); s->state = SPTPS_SECONDARY_KEX; return true; + // TODO: split ACK into a VERify and ACK? default: return error(s, EIO, "Invalid session state %d", s->state); @@ -379,11 +432,13 @@ static bool receive_handshake(sptps_t *s, const char *data, uint16_t len) { // Check datagram for valid HMAC bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len) { - if(!s->instate) + if(!s->instate) { return error(s, EIO, "SPTPS state not ready to verify this datagram"); + } - if(len < 21) + if(len < 21) { return error(s, EIO, "Received short packet in sptps_verify_datagram"); + } uint32_t seqno; memcpy(&seqno, data, 4); @@ -399,23 +454,26 @@ bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len) { static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t len) { const char *data = vdata; - if(len < (s->instate ? 21 : 5)) + if(len < (s->instate ? 21 : 5)) { return error(s, EIO, "Received short packet in sptps_receive_data_datagram"); + } uint32_t seqno; memcpy(&seqno, data, 4); seqno = ntohl(seqno); if(!s->instate) { - if(seqno != s->inseqno) + if(seqno != s->inseqno) { return error(s, EIO, "Invalid packet seqno: %d != %d", seqno, s->inseqno); + } s->inseqno = seqno + 1; uint8_t type = data[4]; - if(type != SPTPS_HANDSHAKE) + if(type != SPTPS_HANDSHAKE) { return error(s, EIO, "Application record received before handshake finished"); + } return receive_handshake(s, data + 5, len - 5); } @@ -426,8 +484,9 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le size_t outlen; - if(!chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen)) + if(!chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen)) { return error(s, EIO, "Failed to decrypt and verify packet"); + } // Replay protection using a sliding window of configurable size. // s->inseqno is expected sequence number @@ -443,12 +502,14 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le memset(s->late, 255, s->replaywin); } else if(seqno < s->inseqno) { // If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it. - if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8))) + if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8))) { return error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno); + } } else { // We missed some packets. Mark them in the bitmap as being late. - for(uint32_t i = s->inseqno; i < seqno; i++) + for(uint32_t i = s->inseqno; i < seqno; i++) { s->late[(i / 8) % s->replaywin] |= 1 << i % 8; + } } } @@ -456,13 +517,15 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le s->late[(seqno / 8) % s->replaywin] &= ~(1 << seqno % 8); } - if(seqno >= s->inseqno) + if(seqno >= s->inseqno) { s->inseqno = seqno + 1; + } - if(!s->inseqno) + if(!s->inseqno) { s->received = 0; - else + } else { s->received++; + } // Append a NULL byte for safety. buffer[len - 20] = 0; @@ -470,33 +533,42 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le uint8_t type = buffer[0]; if(type < SPTPS_HANDSHAKE) { - if(!s->instate) + if(!s->instate) { return error(s, EIO, "Application record received before handshake finished"); - if(!s->receive_record(s->handle, type, buffer + 1, len - 21)) + } + + if(!s->receive_record(s->handle, type, buffer + 1, len - 21)) { abort(); + } } else if(type == SPTPS_HANDSHAKE) { - if(!receive_handshake(s, buffer + 1, len - 21)) + if(!receive_handshake(s, buffer + 1, len - 21)) { abort(); - } else + } + } else { return error(s, EIO, "Invalid record type %d", type); + } return true; } // Receive incoming data. Check if it contains a complete record, if so, handle it. bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { - if(!s->state) + if(!s->state) { return error(s, EIO, "Invalid session state zero"); + } - if(s->datagram) + if(s->datagram) { return sptps_receive_data_datagram(s, data, len); + } while(len) { // First read the 2 length bytes. if(s->buflen < 2) { size_t toread = 2 - s->buflen; - if(toread > len) + + if(toread > len) { toread = len; + } memcpy(s->inbuf + s->buflen, data, toread); @@ -505,8 +577,9 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { data += toread; // Exit early if we don't have the full length. - if(s->buflen < 2) + if(s->buflen < 2) { return true; + } // Get the length bytes @@ -515,18 +588,23 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { // If we have the length bytes, ensure our buffer can hold the whole request. s->inbuf = realloc(s->inbuf, s->reclen + 19UL); - if(!s->inbuf) + + if(!s->inbuf) { return error(s, errno, strerror(errno)); + } // Exit early if we have no more data to process. - if(!len) + if(!len) { return true; + } } // Read up to the end of the record. size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen; - if(toread > len) + + if(toread > len) { toread = len; + } memcpy(s->inbuf + s->buflen, data, toread); s->buflen += toread; @@ -534,8 +612,9 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { data += toread; // If we don't have a whole record, exit. - if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) + if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) { return true; + } // Update sequence number. @@ -543,8 +622,9 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { // Check HMAC and decrypt. if(s->instate) { - if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) + if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) { return error(s, EINVAL, "Failed to decrypt and verify record"); + } } // Append a NULL byte for safety. @@ -553,15 +633,20 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { uint8_t type = s->inbuf[2]; if(type < SPTPS_HANDSHAKE) { - if(!s->instate) + if(!s->instate) { return error(s, EIO, "Application record received before handshake finished"); - if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen)) + } + + if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen)) { return false; + } } else if(type == SPTPS_HANDSHAKE) { - if(!receive_handshake(s, s->inbuf + 3, s->reclen)) + if(!receive_handshake(s, s->inbuf + 3, s->reclen)) { return false; - } else + } + } else { return error(s, EIO, "Invalid record type %d", type); + } s->buflen = 0; } @@ -571,8 +656,9 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { // Start a SPTPS session. bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) { - if(!s || !mykey || !hiskey || !label || !labellen || !send_data || !receive_record) + if(!s || !mykey || !hiskey || !label || !labellen || !send_data || !receive_record) { return error(s, EINVAL, "Invalid argument to sptps_start()"); + } // Initialise struct sptps memset(s, 0, sizeof(*s)); @@ -583,21 +669,30 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_ s->mykey = mykey; s->hiskey = hiskey; s->replaywin = sptps_replaywin; + if(s->replaywin) { s->late = malloc(s->replaywin); - if(!s->late) + + if(!s->late) { return error(s, errno, strerror(errno)); + } + memset(s->late, 0, s->replaywin); } s->label = malloc(labellen); - if(!s->label) + + if(!s->label) { return error(s, errno, strerror(errno)); + } if(!datagram) { s->inbuf = malloc(7); - if(!s->inbuf) + + if(!s->inbuf) { return error(s, errno, strerror(errno)); + } + s->buflen = 0; } diff --git a/src/utcp b/src/utcp index 558c6d18..850542e9 160000 --- a/src/utcp +++ b/src/utcp @@ -1 +1 @@ -Subproject commit 558c6d183e2a580b811c5603dd48c33b01a3dc7e +Subproject commit 850542e9585f716985c25d5995ba5bcb2cc6ba87 diff --git a/src/utils.c b/src/utils.c index 9ec22524..503b16a1 100644 --- a/src/utils.c +++ b/src/utils.c @@ -45,26 +45,32 @@ static const char base64_decode[256] = { }; static int charhex2bin(char c) { - if(isdigit(c)) + if(isdigit(c)) { return c - '0'; - else + } else { return toupper(c) - 'A' + 10; + } } int hex2bin(const char *src, void *vdst, int length) { uint8_t *dst = vdst; int i; - for(i = 0; i < length && isxdigit(src[i * 2]) && isxdigit(src[i * 2 + 1]); i++) + + for(i = 0; i < length && isxdigit(src[i * 2]) && isxdigit(src[i * 2 + 1]); i++) { dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]); + } + return i; } int bin2hex(const void *vsrc, char *dst, int length) { const uint8_t *src = vsrc; + for(int i = length - 1; i >= 0; i--) { dst[i * 2 + 1] = hexadecimals[(unsigned char) src[i] & 15]; dst[i * 2] = hexadecimals[(unsigned char) src[i] >> 4]; } + dst[length * 2] = 0; return length * 2; } @@ -76,9 +82,12 @@ int b64decode(const char *src, void *dst, int length) { for(i = 0; i < length / 3 * 4 && src[i]; i++) { triplet |= base64_decode[src[i] & 0xff] << (6 * (i & 3)); + if((i & 3) == 3) { - if(triplet & 0xff000000U) + if(triplet & 0xff000000U) { return 0; + } + udst[0] = triplet & 0xff; triplet >>= 8; udst[1] = triplet & 0xff; @@ -88,8 +97,11 @@ int b64decode(const char *src, void *dst, int length) { udst += 3; } } - if(triplet & 0xff000000U) + + if(triplet & 0xff000000U) { return 0; + } + if((i & 3) == 3) { udst[0] = triplet & 0xff; triplet >>= 8; @@ -98,8 +110,9 @@ int b64decode(const char *src, void *dst, int length) { } else if((i & 3) == 2) { udst[0] = triplet & 0xff; return i / 4 * 3 + 1; - } else + } else { return i / 4 * 3; + } } static int b64encode_internal(const void *src, char *dst, int length, const char *alphabet) { @@ -119,6 +132,7 @@ static int b64encode_internal(const void *src, char *dst, int length, const char dst[di + 3] = 0; length = di + 2; break; + case 1: triplet = usrc[si]; dst[di] = alphabet[triplet & 63]; @@ -127,6 +141,7 @@ static int b64encode_internal(const void *src, char *dst, int length, const char dst[di + 2] = 0; length = di + 1; break; + default: dst[di] = 0; length = di; @@ -168,12 +183,15 @@ const char *winerror(int err) { ptr = buf + sprintf(buf, "(%d) ", err); if(!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) { strncpy(buf, "(unable to format errormessage)", sizeof(buf)); + } + ; - if((ptr = strchr(buf, '\r'))) - *ptr = '\0'; + if((ptr = strchr(buf, '\r'))) { + * ptr = '\0'; + } return buf; } @@ -181,8 +199,11 @@ const char *winerror(int err) { unsigned int bitfield_to_int(const void *bitfield, size_t size) { unsigned int value = 0; - if(size > sizeof(value)) + + if(size > sizeof(value)) { size = sizeof(value); + } + memcpy(&value, bitfield, size); return value; } diff --git a/src/xalloc.h b/src/xalloc.h index e521d64a..d9f63e05 100644 --- a/src/xalloc.h +++ b/src/xalloc.h @@ -23,31 +23,43 @@ static inline void *xmalloc(size_t n) __attribute__((__malloc__)); static inline void *xmalloc(size_t n) { void *p = malloc(n); - if(!p) + + if(!p) { abort(); + } + return p; } static inline void *xzalloc(size_t n) __attribute__((__malloc__)); static inline void *xzalloc(size_t n) { void *p = calloc(1, n); - if(!p) + + if(!p) { abort(); + } + return p; } static inline void *xrealloc(void *p, size_t n) { p = realloc(p, n); - if(!p) + + if(!p) { abort(); + } + return p; } static inline char *xstrdup(const char *s) __attribute__((__malloc__)); static inline char *xstrdup(const char *s) { char *p = strdup(s); - if(!p) + + if(!p) { abort(); + } + return p; } @@ -55,13 +67,19 @@ static inline int xvasprintf(char **strp, const char *fmt, va_list ap) { #ifdef HAVE_MINGW char buf[1024]; int result = vsnprintf(buf, sizeof(buf), fmt, ap); - if(result < 0) + + if(result < 0) { abort(); + } + *strp = xstrdup(buf); #else int result = vasprintf(strp, fmt, ap); - if(result < 0) + + if(result < 0) { abort(); + } + #endif return result; } -- 2.39.2