From 9cde0d32cf209388cc59b06b7dcb0c3432f97da5 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 5 Oct 2019 14:15:35 +0200 Subject: [PATCH] Add assert() calls to the library. To aid in debugging, start using assert() to ensure preconditions hold. At the moment, we assume that NULL-pointer dereferences will always cause segfaults, so we don't add assert(ptr) statements in those cases, but that might change in the future. --- src/buffer.c | 12 +++++ src/conf.c | 109 ++++++++++++++++++++++++++++++++---------- src/connection.c | 15 ++++-- src/crypto.c | 9 ++++ src/devtools.c | 5 ++ src/discovery.c | 71 +++++++++++++-------------- src/edge.c | 3 ++ src/event.c | 43 ++++++++--------- src/have.h | 1 + src/list.c | 3 ++ src/logger.c | 2 + src/meta.c | 29 ++++++----- src/net.c | 2 + src/net_packet.c | 12 +++++ src/net_socket.c | 2 + src/prf.c | 13 +++++ src/protocol.c | 20 ++++++-- src/protocol_auth.c | 6 +++ src/protocol_edge.c | 6 +++ src/protocol_key.c | 13 +++++ src/protocol_misc.c | 21 ++++++++ src/route.c | 4 ++ src/splay_tree.c | 114 +++++++++++++++++++++++--------------------- src/sptps.c | 15 ++++++ src/submesh.c | 6 +++ 25 files changed, 377 insertions(+), 159 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index cc35918d..c6c34954 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -34,6 +34,8 @@ void buffer_compact(buffer_t *buffer, size_t maxsize) { char *buffer_prepare(buffer_t *buffer, size_t size) { if(!buffer->data) { + assert(!buffer->maxlen); + buffer->maxlen = size; buffer->data = xmalloc(size); } else { @@ -59,12 +61,18 @@ char *buffer_prepare(buffer_t *buffer, size_t size) { // Copy data into the buffer. void buffer_add(buffer_t *buffer, const char *data, size_t size) { + assert(data); + assert(size); + memcpy(buffer_prepare(buffer, size), data, size); } // Remove given number of bytes from the buffer, return a pointer to the start of them. static char *buffer_consume(buffer_t *buffer, size_t size) { + assert(size); + assert(buffer->len - buffer->offset >= size); + char *start = buffer->data + buffer->offset; buffer->offset += size; @@ -94,6 +102,8 @@ 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) { + assert(size); + if(buffer->len - buffer->offset < size) { return NULL; } @@ -102,6 +112,8 @@ char *buffer_read(buffer_t *buffer, size_t size) { } void buffer_clear(buffer_t *buffer) { + assert(!buffer->data == !buffer->maxlen); + free(buffer->data); buffer->data = NULL; buffer->maxlen = 0; diff --git a/src/conf.c b/src/conf.c index 3003a6f4..0363cde5 100644 --- a/src/conf.c +++ b/src/conf.c @@ -31,26 +31,47 @@ /// Generate a path to the main configuration file. static void make_main_path(meshlink_handle_t *mesh, const char *conf_subdir, char *path, size_t len) { + assert(conf_subdir); + assert(path); + assert(len); + snprintf(path, len, "%s" SLASH "%s" SLASH "meshlink.conf", mesh->confbase, conf_subdir); } /// Generate a path to a host configuration file. static void make_host_path(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, char *path, size_t len) { + assert(conf_subdir); + assert(name); + assert(path); + assert(len); + snprintf(path, len, "%s" SLASH "%s" SLASH "hosts" SLASH "%s", mesh->confbase, conf_subdir, name); } /// Generate a path to an unused invitation file. static void make_invitation_path(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, char *path, size_t len) { + assert(conf_subdir); + assert(name); + assert(path); + assert(len); + snprintf(path, len, "%s" SLASH "%s" SLASH "invitations" SLASH "%s", mesh->confbase, conf_subdir, name); } /// Generate a path to a used invitation file. static void make_used_invitation_path(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, char *path, size_t len) { + assert(conf_subdir); + assert(name); + assert(path); + assert(len); + snprintf(path, len, "%s" SLASH "%s" SLASH "invitations" SLASH "%s.used", mesh->confbase, conf_subdir, name); } /// Remove a directory recursively static void deltree(const char *dirname) { + assert(dirname); + DIR *d = opendir(dirname); if(d) { @@ -76,6 +97,8 @@ static void deltree(const char *dirname) { } static bool sync_path(const char *pathname) { + assert(pathname); + int fd = open(pathname, O_RDONLY); if(fd < 0) { @@ -103,9 +126,9 @@ static bool sync_path(const char *pathname) { /// Try decrypting the main configuration file from the given sub-directory. static bool main_config_decrypt(meshlink_handle_t *mesh, const char *conf_subdir) { - if(!mesh->config_key && !mesh->confbase && !conf_subdir) { - return false; - } + assert(mesh->config_key); + assert(mesh->confbase); + assert(conf_subdir); config_t config; @@ -124,14 +147,12 @@ static bool main_config_decrypt(meshlink_handle_t *mesh, const char *conf_subdir /// Create a fresh configuration directory bool config_init(meshlink_handle_t *mesh, const char *conf_subdir) { + assert(conf_subdir); + if(!mesh->confbase) { return true; } - if(!conf_subdir) { - return false; - } - if(mkdir(mesh->confbase, 0700) && errno != EEXIST) { logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", mesh->confbase, strerror(errno)); return false; @@ -167,7 +188,9 @@ bool config_init(meshlink_handle_t *mesh, const char *conf_subdir) { /// Wipe an existing configuration directory bool config_destroy(const char *confbase, const char *conf_subdir) { - if(!confbase && !conf_subdir) { + assert(conf_subdir); + + if(!confbase) { return false; } @@ -205,9 +228,8 @@ bool config_destroy(const char *confbase, const char *conf_subdir) { } static bool copytree(const char *src_dir_name, const void *src_key, const char *dst_dir_name, const void *dst_key) { - if(!src_dir_name || !dst_dir_name) { - return false; - } + assert(src_dir_name); + assert(dst_dir_name); char src_filename[PATH_MAX]; char dst_filename[PATH_MAX]; @@ -312,6 +334,9 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * } bool config_copy(meshlink_handle_t *mesh, const char *src_dir_name, const void *src_key, const char *dst_dir_name, const void *dst_key) { + assert(src_dir_name); + assert(dst_dir_name); + char src_filename[PATH_MAX]; char dst_filename[PATH_MAX]; @@ -323,7 +348,9 @@ bool config_copy(meshlink_handle_t *mesh, const char *src_dir_name, const void * /// Check the presence of the main configuration file. bool main_config_exists(meshlink_handle_t *mesh, const char *conf_subdir) { - if(!mesh->confbase && !conf_subdir) { + assert(conf_subdir); + + if(!mesh->confbase) { return false; } @@ -333,7 +360,10 @@ bool main_config_exists(meshlink_handle_t *mesh, const char *conf_subdir) { } bool config_rename(meshlink_handle_t *mesh, const char *old_conf_subdir, const char *new_conf_subdir) { - if(!mesh->confbase && !old_conf_subdir && !new_conf_subdir) { + assert(old_conf_subdir); + assert(new_conf_subdir); + + if(!mesh->confbase) { return false; } @@ -347,14 +377,12 @@ bool config_rename(meshlink_handle_t *mesh, const char *old_conf_subdir, const c } bool config_sync(meshlink_handle_t *mesh, const char *conf_subdir) { + assert(conf_subdir); + if(!mesh->confbase) { return true; } - if(!conf_subdir) { - return false; - } - char path[PATH_MAX]; snprintf(path, sizeof(path), "%s" SLASH "%s" SLASH "hosts", mesh->confbase, conf_subdir); @@ -476,6 +504,8 @@ void main_config_unlock(meshlink_handle_t *mesh) { /// Read a configuration file from a FILE handle. bool config_read_file(meshlink_handle_t *mesh, FILE *f, config_t *config, const void *key) { + assert(f); + long len; if(fseek(f, 0, SEEK_END) || !(len = ftell(f)) || fseek(f, 0, SEEK_SET)) { @@ -522,6 +552,8 @@ bool config_read_file(meshlink_handle_t *mesh, FILE *f, config_t *config, const /// Write a configuration file to a FILE handle. bool config_write_file(meshlink_handle_t *mesh, FILE *f, const config_t *config, const void *key) { + assert(f); + if(key) { uint8_t buf[config->len + 16]; size_t len = sizeof(buf); @@ -558,6 +590,8 @@ bool config_write_file(meshlink_handle_t *mesh, FILE *f, const config_t *config, /// Free resources of a loaded configuration file. void config_free(config_t *config) { + assert(!config->len || config->buf); + free((uint8_t *)config->buf); config->buf = NULL; config->len = 0; @@ -565,7 +599,9 @@ void config_free(config_t *config) { /// Check the presence of a host configuration file. bool config_exists(meshlink_handle_t *mesh, const char *conf_subdir, const char *name) { - if(!mesh->confbase && !conf_subdir) { + assert(conf_subdir); + + if(!mesh->confbase) { return false; } @@ -577,7 +613,9 @@ bool config_exists(meshlink_handle_t *mesh, const char *conf_subdir, const char /// Read a host configuration file. bool config_read(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, config_t *config, void *key) { - if(!mesh->confbase && !conf_subdir) { + assert(conf_subdir); + + if(!mesh->confbase) { return false; } @@ -603,7 +641,10 @@ bool config_read(meshlink_handle_t *mesh, const char *conf_subdir, const char *n } bool config_scan_all(meshlink_handle_t *mesh, const char *conf_subdir, const char *conf_type, config_scan_action_t action, void *arg) { - if(!mesh->confbase && !conf_subdir && !conf_type) { + assert(conf_subdir); + assert(conf_type); + + if(!mesh->confbase) { return false; } @@ -637,7 +678,11 @@ bool config_scan_all(meshlink_handle_t *mesh, const char *conf_subdir, const cha /// Write a host configuration file. bool config_write(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, const config_t *config, void *key) { - if(!mesh->confbase && !conf_subdir && !name) { + assert(conf_subdir); + assert(name); + assert(config); + + if(!mesh->confbase) { return true; } @@ -680,7 +725,10 @@ bool config_write(meshlink_handle_t *mesh, const char *conf_subdir, const char * /// Read the main configuration file. bool main_config_read(meshlink_handle_t *mesh, const char *conf_subdir, config_t *config, void *key) { - if(!mesh->confbase && !conf_subdir) { + assert(conf_subdir); + assert(config); + + if(!mesh->confbase) { return false; } @@ -707,7 +755,10 @@ bool main_config_read(meshlink_handle_t *mesh, const char *conf_subdir, config_t /// Write the main configuration file. bool main_config_write(meshlink_handle_t *mesh, const char *conf_subdir, const config_t *config, void *key) { - if(!mesh->confbase && !conf_subdir) { + assert(conf_subdir); + assert(config); + + if(!mesh->confbase) { return true; } @@ -751,7 +802,11 @@ bool main_config_write(meshlink_handle_t *mesh, const char *conf_subdir, const c /// Read an invitation file from the confbase sub-directory, and immediately delete it. bool invitation_read(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, config_t *config, void *key) { - if(!mesh->confbase && !conf_subdir) { + assert(conf_subdir); + assert(name); + assert(config); + + if(!mesh->confbase) { return false; } @@ -810,7 +865,11 @@ bool invitation_read(meshlink_handle_t *mesh, const char *conf_subdir, const cha /// Write an invitation file. bool invitation_write(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, const config_t *config, void *key) { - if(!mesh->confbase && !conf_subdir) { + assert(conf_subdir); + assert(name); + assert(config); + + if(!mesh->confbase) { return false; } diff --git a/src/connection.c b/src/connection.c index adecae8b..9cc64914 100644 --- a/src/connection.c +++ b/src/connection.c @@ -29,6 +29,9 @@ #include "xalloc.h" void init_connections(meshlink_handle_t *mesh) { + assert(!mesh->connections); + assert(!mesh->everyone); + mesh->connections = list_alloc((list_action_t) free_connection); mesh->everyone = new_connection(); mesh->everyone->name = xstrdup("mesh->everyone"); @@ -39,7 +42,9 @@ void exit_connections(meshlink_handle_t *mesh) { list_delete_list(mesh->connections); } - free_connection(mesh->everyone); + if(mesh->everyone) { + free_connection(mesh->everyone); + } mesh->connections = NULL; mesh->everyone = NULL; @@ -50,9 +55,7 @@ connection_t *new_connection(void) { } void free_connection(connection_t *c) { - if(!c) { - return; - } + assert(c); sptps_stop(&c->sptps); ecdsa_free(c->ecdsa); @@ -74,11 +77,15 @@ void free_connection(connection_t *c) { } void connection_add(meshlink_handle_t *mesh, connection_t *c) { + assert(c); + c->mesh = mesh; list_insert_tail(mesh->connections, c); } void connection_del(meshlink_handle_t *mesh, connection_t *c) { + assert(c); + io_del(&mesh->loop, &c->io); list_delete(mesh->connections, c); } diff --git a/src/crypto.c b/src/crypto.c index 1bdd8b07..3244a0b4 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -28,6 +28,8 @@ static int random_fd = -1; void crypto_init(void) { + assert(random_fd == -1); + random_fd = open("/dev/urandom", O_RDONLY); if(random_fd < 0) { @@ -41,10 +43,15 @@ void crypto_init(void) { } void crypto_exit(void) { + assert(random_fd != -1); + close(random_fd); + random_fd = -1; } void randomize(void *out, size_t outlen) { + assert(outlen); + char *ptr = out; while(outlen) { @@ -81,6 +88,8 @@ void crypto_exit(void) { } void randomize(void *out, size_t outlen) { + assert(outlen); + if(!CryptGenRandom(prov, outlen, out)) { fprintf(stderr, "CryptGenRandom() failed\n"); abort(); diff --git a/src/devtools.c b/src/devtools.c index 47f18bc6..0284dcd5 100644 --- a/src/devtools.c +++ b/src/devtools.c @@ -106,6 +106,8 @@ devtool_edge_t *devtool_get_all_edges(meshlink_handle_t *mesh, devtool_edge_t *e } static bool fstrwrite(const char *str, FILE *stream) { + assert(stream); + size_t len = strlen(str); if(fwrite((void *)str, 1, len, stream) != len) { @@ -116,6 +118,8 @@ static bool fstrwrite(const char *str, FILE *stream) { } bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream) { + assert(stream); + bool result = true; pthread_mutex_lock(&(mesh->mesh_mutex)); @@ -309,6 +313,7 @@ meshlink_submesh_t **devtool_get_all_submeshes(meshlink_handle_t *mesh, meshlink return result; } + meshlink_handle_t *devtool_open_in_netns(const char *confbase, const char *name, const char *appname, dev_class_t devclass, int netns) { meshlink_open_params_t *params = meshlink_open_params_init(confbase, name, appname, devclass); params->netns = dup(netns); diff --git a/src/discovery.c b/src/discovery.c index ae2cf895..2af47023 100644 --- a/src/discovery.c +++ b/src/discovery.c @@ -22,6 +22,8 @@ #define MESHLINK_MDNS_FINGERPRINT_KEY "fingerprint" static void generate_rand_string(char *buffer, size_t size) { + assert(size); + for(size_t i = 0; i < (size - 1); ++i) { buffer[i] = 'a' + (rand() % ('z' - 'a' + 1)); } @@ -34,10 +36,9 @@ static void discovery_entry_group_callback(CattaServer *server, CattaSEntryGroup (void)group; meshlink_handle_t *mesh = userdata; - // asserts - assert(mesh != NULL); - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); + assert(mesh); + assert(mesh->catta_server); + assert(mesh->catta_poll); /* Called whenever the entry group state changes */ switch(state) { @@ -69,14 +70,13 @@ static void discovery_create_services(meshlink_handle_t *mesh) { char *txt_name = NULL; char *txt_fingerprint = NULL; - // asserts - assert(mesh != NULL); - assert(mesh->name != NULL); - assert(mesh->myport != NULL); - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); - assert(mesh->catta_servicetype != NULL); - assert(mesh->self != NULL); + assert(mesh); + assert(mesh->name); + assert(mesh->myport); + assert(mesh->catta_server); + assert(mesh->catta_poll); + assert(mesh->catta_servicetype); + assert(mesh->self); logger(mesh, MESHLINK_DEBUG, "Adding service\n"); @@ -122,8 +122,7 @@ static void discovery_server_callback(CattaServer *server, CattaServerState stat (void)server; meshlink_handle_t *mesh = userdata; - // asserts - assert(mesh != NULL); + assert(mesh); switch(state) { case CATTA_SERVER_RUNNING: @@ -145,10 +144,9 @@ static void discovery_server_callback(CattaServer *server, CattaServerState stat generate_rand_string(hostname, sizeof(hostname)); pthread_mutex_lock(&(mesh->mesh_mutex)); - // - // asserts - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); + + assert(mesh->catta_server); + assert(mesh->catta_poll); int result = catta_server_set_host_name(mesh->catta_server, hostname); @@ -178,9 +176,8 @@ static void discovery_server_callback(CattaServer *server, CattaServerState stat case CATTA_SERVER_FAILURE: pthread_mutex_lock(&(mesh->mesh_mutex)); - // asserts - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); + assert(mesh->catta_server); + assert(mesh->catta_poll); /* Terminate on failure */ catta_simple_poll_quit(mesh->catta_poll); @@ -204,6 +201,8 @@ static void discovery_resolve_callback(CattaSServiceResolver *resolver, CattaIfI meshlink_handle_t *mesh = userdata; + assert(mesh); + if(event != CATTA_RESOLVER_FOUND) { catta_s_service_resolver_free(resolver); return; @@ -213,7 +212,7 @@ static void discovery_resolve_callback(CattaSServiceResolver *resolver, CattaIfI CattaStringList *node_name_li = catta_string_list_find(txt, MESHLINK_MDNS_NAME_KEY); CattaStringList *node_fp_li = catta_string_list_find(txt, MESHLINK_MDNS_FINGERPRINT_KEY); - if(node_name_li != NULL && node_fp_li != NULL) { + if(node_name_li && node_fp_li) { char *node_name = (char *)catta_string_list_get_text(node_name_li) + strlen(MESHLINK_MDNS_NAME_KEY); char *node_fp = (char *)catta_string_list_get_text(node_fp_li) + strlen(MESHLINK_MDNS_FINGERPRINT_KEY); @@ -224,7 +223,7 @@ static void discovery_resolve_callback(CattaSServiceResolver *resolver, CattaIfI meshlink_node_t *node = meshlink_get_node(mesh, node_name); - if(node != NULL) { + if(node) { logger(mesh, MESHLINK_INFO, "Node %s is part of the mesh network.\n", node->name); sockaddr_t naddress; @@ -342,7 +341,7 @@ static void discovery_log_cb(CattaLogLevel level, const char *txt) { static void *discovery_loop(void *userdata) { bool status = false; meshlink_handle_t *mesh = userdata; - assert(mesh != NULL); + assert(mesh); // handle catta logs catta_set_log_function(discovery_log_cb); @@ -423,7 +422,7 @@ fail: catta_simple_poll_loop(mesh->catta_poll); } - if(mesh->catta_browser != NULL) { + if(mesh->catta_browser) { catta_s_service_browser_free(mesh->catta_browser); mesh->catta_browser = NULL; } @@ -434,17 +433,17 @@ fail: mesh->catta_group = NULL; } - if(mesh->catta_server != NULL) { + if(mesh->catta_server) { catta_server_free(mesh->catta_server); mesh->catta_server = NULL; } - if(mesh->catta_poll != NULL) { + if(mesh->catta_poll) { catta_simple_poll_free(mesh->catta_poll); mesh->catta_poll = NULL; } - if(mesh->catta_servicetype != NULL) { + if(mesh->catta_servicetype) { free(mesh->catta_servicetype); mesh->catta_servicetype = NULL; } @@ -455,13 +454,12 @@ fail: bool discovery_start(meshlink_handle_t *mesh) { logger(mesh, MESHLINK_DEBUG, "discovery_start called\n"); - // asserts - assert(mesh != NULL); - assert(mesh->catta_poll == NULL); - assert(mesh->catta_server == NULL); - assert(mesh->catta_browser == NULL); - assert(mesh->discovery_threadstarted == false); - assert(mesh->catta_servicetype == NULL); + assert(mesh); + assert(!mesh->catta_poll); + assert(!mesh->catta_server); + assert(!mesh->catta_browser); + assert(!mesh->discovery_threadstarted); + assert(!mesh->catta_servicetype); // Start the discovery thread if(pthread_create(&mesh->discovery_thread, NULL, discovery_loop, mesh) != 0) { @@ -482,8 +480,7 @@ bool discovery_start(meshlink_handle_t *mesh) { void discovery_stop(meshlink_handle_t *mesh) { logger(mesh, MESHLINK_DEBUG, "discovery_stop called\n"); - // asserts - assert(mesh != NULL); + assert(mesh); // Shut down if(mesh->catta_poll) { diff --git a/src/edge.c b/src/edge.c index f3d21d93..afe9cfe3 100644 --- a/src/edge.c +++ b/src/edge.c @@ -103,6 +103,9 @@ void edge_del(meshlink_handle_t *mesh, edge_t *e) { } edge_t *lookup_edge(node_t *from, node_t *to) { + assert(from); + assert(to); + edge_t v; v.from = from; diff --git a/src/event.c b/src/event.c index f88112ff..90f56944 100644 --- a/src/event.c +++ b/src/event.c @@ -62,9 +62,7 @@ static int timeout_compare(const timeout_t *a, const timeout_t *b) { } void io_add(event_loop_t *loop, io_t *io, io_cb_t cb, void *data, int fd, int flags) { - if(io->cb) { - return; - } + assert(!io->cb); io->fd = fd; io->cb = cb; @@ -73,12 +71,12 @@ 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)) { - abort(); - } + assert(splay_insert_node(&loop->ios, &io->node)); } void io_set(event_loop_t *loop, io_t *io, int flags) { + assert(io->cb); + io->flags = flags; if(flags & IO_READ) { @@ -95,9 +93,7 @@ void io_set(event_loop_t *loop, io_t *io, int flags) { } void io_del(event_loop_t *loop, io_t *io) { - if(!io->cb) { - return; - } + assert(io->cb); loop->deletion = true; @@ -116,6 +112,8 @@ void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void * } void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timeval *tv) { + assert(timeout->cb); + if(timerisset(&timeout->tv)) { splay_unlink_node(&loop->timeouts, &timeout->node); } @@ -176,9 +174,8 @@ static void signalio_handler(event_loop_t *loop, void *data, int flags) { } static void pipe_init(event_loop_t *loop) { - if(!pipe(loop->pipefd)) { - io_add(loop, &loop->signalio, signalio_handler, NULL, loop->pipefd[0], IO_READ); - } + assert(pipe(loop->pipefd) == 0); + io_add(loop, &loop->signalio, signalio_handler, NULL, loop->pipefd[0], IO_READ); } static void pipe_exit(event_loop_t *loop) { @@ -198,9 +195,7 @@ 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) { - return; - } + assert(!sig->cb); sig->cb = cb; sig->data = data; @@ -217,9 +212,7 @@ void signal_add(event_loop_t *loop, signal_t *sig, signal_cb_t cb, void *data, u } void signal_del(event_loop_t *loop, signal_t *sig) { - if(!sig->cb) { - return; - } + assert(sig->cb); loop->deletion = true; @@ -237,6 +230,8 @@ void idle_set(event_loop_t *loop, idle_cb_t cb, void *data) { } bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { + assert(mutex); + fd_set readable; fd_set writable; @@ -276,15 +271,11 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { } // release mesh mutex during select - if(mutex) { - pthread_mutex_unlock(mutex); - } + pthread_mutex_unlock(mutex); int n = select(fds, &readable, &writable, NULL, tv); - if(mutex) { - pthread_mutex_lock(mutex); - } + pthread_mutex_lock(mutex); gettimeofday(&loop->now, NULL); @@ -353,6 +344,10 @@ void event_loop_init(event_loop_t *loop) { } void event_loop_exit(event_loop_t *loop) { + assert(!loop->ios.count); + assert(!loop->timeouts.count); + assert(!loop->signals.count); + for splay_each(io_t, io, &loop->ios) { splay_unlink_node(&loop->ios, node); } diff --git a/src/have.h b/src/have.h index d4c62f48..f64e15d0 100644 --- a/src/have.h +++ b/src/have.h @@ -42,6 +42,7 @@ #include #include #include +#include #ifdef HAVE_MINGW #include diff --git a/src/list.c b/src/list.c index c75cf146..8a483604 100644 --- a/src/list.c +++ b/src/list.c @@ -186,8 +186,11 @@ void *list_get_tail(list_t *list) { void list_delete_list(list_t *list) { for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) { list_free_node(list, node); + list->count--; } + assert(!list->count); + list_free(list); } diff --git a/src/logger.c b/src/logger.c index 48c9564c..78d629ee 100644 --- a/src/logger.c +++ b/src/logger.c @@ -25,6 +25,8 @@ // TODO: refactor logging code to use a meshlink_handle_t *. void logger(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *format, ...) { + assert(format); + if(mesh) { if(level < mesh->log_level || !mesh->log_cb) { return; diff --git a/src/meta.c b/src/meta.c index d293b2ee..f3ab47f1 100644 --- a/src/meta.c +++ b/src/meta.c @@ -30,14 +30,14 @@ bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t length) { (void)type; + + assert(handle); + assert(buffer); + assert(length); + connection_t *c = handle; meshlink_handle_t *mesh = c->mesh; - if(!c) { - logger(mesh, MESHLINK_ERROR, "send_meta_sptps() called with NULL pointer!"); - abort(); - } - buffer_add(&c->outbuf, (const char *)buffer, length); io_set(&mesh->loop, &c->io, IO_READ | IO_WRITE); @@ -45,10 +45,9 @@ bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t leng } bool send_meta(meshlink_handle_t *mesh, connection_t *c, const char *buffer, int length) { - if(!c) { - logger(mesh, MESHLINK_ERROR, "send_meta() called with NULL pointer!"); - abort(); - } + assert(c); + assert(buffer); + assert(length); logger(mesh, MESHLINK_DEBUG, "Sending %d bytes of metadata to %s", length, c->name); @@ -62,14 +61,19 @@ 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) { + assert(buffer); + assert(length); + for list_each(connection_t, c, mesh->connections) if(c != from && c->status.active) { send_meta(mesh, c, buffer, length); } } -void broadcast_submesh_meta(meshlink_handle_t *mesh, connection_t *from, submesh_t *s, - const char *buffer, int length) { +void broadcast_submesh_meta(meshlink_handle_t *mesh, connection_t *from, submesh_t *s, const char *buffer, int length) { + assert(buffer); + assert(length); + for list_each(connection_t, c, mesh->connections) if(c != from && c->status.active) { if(c->node && submesh_allows_node(s, c->node)) { @@ -79,6 +83,9 @@ void broadcast_submesh_meta(meshlink_handle_t *mesh, connection_t *from, submesh } bool receive_meta_sptps(void *handle, uint8_t type, const void *data, uint16_t length) { + assert(handle); + assert(!length || data); + connection_t *c = handle; meshlink_handle_t *mesh = c->mesh; char *request = (char *)data; diff --git a/src/net.c b/src/net.c index 1e2e00cd..46a2631e 100644 --- a/src/net.c +++ b/src/net.c @@ -109,6 +109,8 @@ void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report) and close the connection. */ static void timeout_handler(event_loop_t *loop, void *data) { + assert(data); + meshlink_handle_t *mesh = loop->data; logger(mesh, MESHLINK_DEBUG, "timeout_handler()"); diff --git a/src/net_packet.c b/src/net_packet.c index c8165327..493a38ff 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -155,6 +155,11 @@ void send_mtu_probe(meshlink_handle_t *mesh, node_t *n) { } static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet, uint16_t len) { + if(len < 64) { + logger(mesh, MESHLINK_WARNING, "Got too short MTU probe length %d from %s", packet->len, n->name); + return; + } + logger(mesh, MESHLINK_DEBUG, "Got MTU probe length %d from %s", packet->len, n->name); if(!packet->data[0]) { @@ -357,6 +362,10 @@ static void send_udppacket(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *ori } bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) { + assert(handle); + assert(data); + assert(len); + node_t *to = handle; meshlink_handle_t *mesh = to->mesh; @@ -405,6 +414,9 @@ bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) { } bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len) { + assert(handle); + assert(!data || len); + node_t *from = handle; meshlink_handle_t *mesh = from->mesh; diff --git a/src/net_socket.c b/src/net_socket.c index 29f14c0e..51e0cacc 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -238,6 +238,8 @@ int setup_vpn_in_socket(meshlink_handle_t *mesh, const sockaddr_t *sa) { } /* int setup_vpn_in_socket */ static void retry_outgoing_handler(event_loop_t *loop, void *data) { + assert(data); + meshlink_handle_t *mesh = loop->data; outgoing_t *outgoing = data; setup_outgoing_connection(mesh, outgoing); diff --git a/src/prf.c b/src/prf.c index 499d8196..3e1b0b54 100644 --- a/src/prf.c +++ b/src/prf.c @@ -23,6 +23,9 @@ #include "ed25519/sha512.h" static void memxor(char *buf, char c, size_t len) { + assert(buf); + assert(len); + for(size_t i = 0; i < len; i++) { buf[i] ^= c; } @@ -33,6 +36,9 @@ static void memxor(char *buf, char c, size_t len) { // TODO: separate key setup from hmac_sha512 static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t msglen, char *out) { + assert(msg); + assert(msglen); + char tmp[2 * mdlen]; sha512_context md; @@ -80,6 +86,13 @@ static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t */ bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) { + assert(secret); + assert(secretlen); + assert(seed); + assert(seedlen); + assert(out); + assert(outlen); + /* Data is what the "inner" HMAC function processes. It consists of the previous HMAC result plus the seed. */ diff --git a/src/protocol.c b/src/protocol.c index 92418f17..3886e357 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -67,14 +67,14 @@ bool check_id(const char *id) { detection as well */ bool send_request(meshlink_handle_t *mesh, connection_t *c, submesh_t *s, const char *format, ...) { + assert(c); + assert(format); + assert(*format); + va_list args; char request[MAXBUFSIZE]; int len; - if(!c) { - return false; - } - /* Use vsnprintf instead of vxasprintf: faster, no memory fragmentation, cleanup is automatic, and there is a limit on the input buffer anyway */ @@ -107,6 +107,10 @@ bool send_request(meshlink_handle_t *mesh, connection_t *c, submesh_t *s, const } void forward_request(meshlink_handle_t *mesh, connection_t *from, submesh_t *s, const char *request) { + assert(from); + assert(request); + assert(*request); + logger(mesh, MESHLINK_DEBUG, "Forwarding %s from %s: %s", request_name[atoi(request)], from->name, request); // Create a temporary newline-terminated copy of the request @@ -124,6 +128,9 @@ void forward_request(meshlink_handle_t *mesh, connection_t *from, submesh_t *s, } bool receive_request(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + if(c->outgoing && mesh->proxytype == PROXY_HTTP && c->allow_request == ID) { if(!request[0] || request[0] == '\r') { return true; @@ -208,6 +215,9 @@ static void age_past_requests(event_loop_t *loop, void *data) { } bool seen_request(meshlink_handle_t *mesh, const char *request) { + assert(request); + assert(*request); + past_request_t *new, p = {.request = request}; if(splay_search(mesh->past_request_tree, &p)) { @@ -230,6 +240,8 @@ bool seen_request(meshlink_handle_t *mesh, const char *request) { } void init_requests(meshlink_handle_t *mesh) { + assert(!mesh->past_request_tree); + mesh->past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request); timeout_add(&mesh->loop, &mesh->past_request_timeout, age_past_requests, NULL, &(struct timeval) { 0, 0 diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 5ae4501e..12e81e4c 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -248,6 +248,9 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat } bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + char name[MAX_STRING_SIZE]; if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) { @@ -385,6 +388,9 @@ static void send_everything(meshlink_handle_t *mesh, connection_t *c) { } bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + char hisport[MAX_STRING_SIZE]; int devclass; uint32_t options; diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 74ace0cc..8bb70714 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -84,6 +84,9 @@ bool send_add_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e, in } bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + edge_t *e; node_t *from, *to; char from_name[MAX_STRING_SIZE]; @@ -275,6 +278,9 @@ bool send_del_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e, in } bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + edge_t *e; char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; diff --git a/src/protocol_key.c b/src/protocol_key.c index 836737aa..a9bc1c0a 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -45,6 +45,9 @@ void send_key_changed(meshlink_handle_t *mesh) { } bool key_changed_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + char name[MAX_STRING_SIZE]; node_t *n; @@ -73,6 +76,10 @@ bool key_changed_h(meshlink_handle_t *mesh, connection_t *c, const char *request static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) { (void)type; + + assert(data); + assert(len); + node_t *to = handle; meshlink_handle_t *mesh = to->mesh; to->sptps.send_data = send_sptps_data; @@ -211,6 +218,9 @@ static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char * } bool req_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; node_t *from, *to; @@ -272,6 +282,9 @@ bool send_ans_key(meshlink_handle_t *mesh, node_t *to) { } bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; char key[MAX_STRING_SIZE]; diff --git a/src/protocol_misc.c b/src/protocol_misc.c index dde4bbb4..af3caddf 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -34,6 +34,9 @@ int maxoutbufsize = 0; /* Status and error notification routines */ bool status_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + int statusno; char statusstring[MAX_STRING_SIZE]; @@ -48,6 +51,9 @@ bool status_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { } bool error_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + int err; char errorstring[MAX_STRING_SIZE]; @@ -65,6 +71,10 @@ bool termreq_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { (void)mesh; (void)c; (void)request; + + assert(request); + assert(*request); + return false; } @@ -77,6 +87,10 @@ bool send_ping(meshlink_handle_t *mesh, connection_t *c) { bool ping_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { (void)request; + + assert(request); + assert(*request); + return send_pong(mesh, c); } @@ -87,6 +101,10 @@ bool send_pong(meshlink_handle_t *mesh, connection_t *c) { bool pong_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { (void)mesh; (void)request; + + assert(request); + assert(*request); + c->status.pinged = false; /* Successful connection, reset timeout if this is an outgoing connection. */ @@ -110,6 +128,9 @@ bool pong_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { /* Sending and receiving packets via TCP */ bool tcppacket_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { + assert(request); + assert(*request); + short int len; if(sscanf(request, "%*d %hd", &len) != 1) { diff --git a/src/route.c b/src/route.c index 4de61026..ee36a9bf 100644 --- a/src/route.c +++ b/src/route.c @@ -26,6 +26,8 @@ #include "utils.h" static bool checklength(node_t *source, vpn_packet_t *packet, uint16_t length) { + assert(length); + if(packet->len < length) { logger(source->mesh, MESHLINK_WARNING, "Got too short packet from %s", source->name); return false; @@ -35,6 +37,8 @@ static bool checklength(node_t *source, vpn_packet_t *packet, uint16_t length) { } void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) { + assert(source); + // TODO: route on name or key meshlink_packethdr_t *hdr = (meshlink_packethdr_t *) packet->data; diff --git a/src/splay_tree.c b/src/splay_tree.c index 51439259..53f109f2 100644 --- a/src/splay_tree.c +++ b/src/splay_tree.c @@ -409,59 +409,6 @@ splay_node_t *splay_search_closest_greater_node(splay_tree_t *tree, const void * /* Insertion and deletion */ -splay_node_t *splay_insert(splay_tree_t *tree, void *data) { - splay_node_t *closest, *new; - int result; - - if(!tree->root) { - new = splay_alloc_node(); - new->data = data; - splay_insert_top(tree, new); - } else { - closest = splay_search_closest_node(tree, data, &result); - - if(!result) { - return NULL; - } - - new = splay_alloc_node(); - new->data = data; - - if(result < 0) { - splay_insert_before(tree, closest, new); - } else { - splay_insert_after(tree, closest, new); - } - } - - return new; -} - -splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) { - splay_node_t *closest; - int result; - - node->left = node->right = node->parent = node->next = node->prev = NULL; - - if(!tree->root) { - splay_insert_top(tree, node); - } else { - closest = splay_search_closest_node(tree, node->data, &result); - - if(!result) { - return NULL; - } - - if(result < 0) { - splay_insert_before(tree, closest, node); - } else { - splay_insert_after(tree, closest, node); - } - } - - return node; -} - void splay_insert_top(splay_tree_t *tree, splay_node_t *node) { node->prev = node->next = node->left = node->right = node->parent = NULL; tree->head = tree->tail = tree->root = node; @@ -542,6 +489,59 @@ void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *n tree->count++; } +splay_node_t *splay_insert(splay_tree_t *tree, void *data) { + splay_node_t *closest, *new; + int result; + + if(!tree->root) { + new = splay_alloc_node(); + new->data = data; + splay_insert_top(tree, new); + } else { + closest = splay_search_closest_node(tree, data, &result); + + if(!result) { + return NULL; + } + + new = splay_alloc_node(); + new->data = data; + + if(result < 0) { + splay_insert_before(tree, closest, new); + } else { + splay_insert_after(tree, closest, new); + } + } + + return new; +} + +splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) { + splay_node_t *closest; + int result; + + node->left = node->right = node->parent = node->next = node->prev = NULL; + + if(!tree->root) { + splay_insert_top(tree, node); + } else { + closest = splay_search_closest_node(tree, node->data, &result); + + if(!result) { + return NULL; + } + + if(result < 0) { + splay_insert_before(tree, closest, node); + } else { + splay_insert_after(tree, closest, node); + } + } + + return node; +} + splay_node_t *splay_unlink(splay_tree_t *tree, void *data) { splay_node_t *node; @@ -555,6 +555,10 @@ splay_node_t *splay_unlink(splay_tree_t *tree, void *data) { } void splay_unlink_node(splay_tree_t *tree, splay_node_t *node) { + assert(tree->count); + assert(node->prev || tree->head == node); + assert(node->next || tree->tail == node); + if(node->prev) { node->prev->next = node->next; } else { @@ -607,9 +611,11 @@ void splay_delete_tree(splay_tree_t *tree) { for(splay_node_t *node = tree->head, *next; node; node = next) { next = node->next; splay_free_node(tree, node); + tree->count--; } - splay_free_tree(tree); + assert(!tree->count); + free(tree); } /* Tree walking */ diff --git a/src/sptps.c b/src/sptps.c index be16d5ea..ed1f67ff 100644 --- a/src/sptps.c +++ b/src/sptps.c @@ -52,11 +52,16 @@ void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap) { (void)s_errno; (void)format; (void)ap; + + assert(format); } void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap) { (void)s; (void)s_errno; + + assert(format); + vfprintf(stderr, format, ap); fputc('\n', stderr); } @@ -65,6 +70,9 @@ void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap) = spt // Log an error message. static bool error(sptps_t *s, int s_errno, const char *format, ...) { + assert(s_errno); + assert(format); + if(format) { va_list ap; va_start(ap, format); @@ -77,6 +85,8 @@ static bool error(sptps_t *s, int s_errno, const char *format, ...) { } static void warning(sptps_t *s, const char *format, ...) { + assert(format); + va_list ap; va_start(ap, format); sptps_log(s, 0, format, ap); @@ -132,6 +142,8 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_ // Send an application record. bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len) { + assert(!len || data); + // Sanity checks: application cannot send data before handshake is finished, // and only record types 0..127 are allowed. if(!s->outstate) { @@ -199,6 +211,9 @@ static bool send_sig(sptps_t *s) { // Generate key material from the shared secret created from the ECDHE key exchange. static bool generate_key_material(sptps_t *s, const char *shared, size_t len) { + assert(shared); + assert(len); + // Initialise cipher and digest structures if necessary if(!s->outstate) { s->incipher = chacha_poly1305_init(); diff --git a/src/submesh.c b/src/submesh.c index a3bccc14..6780b8a0 100644 --- a/src/submesh.c +++ b/src/submesh.c @@ -31,6 +31,7 @@ #include "protocol.h" void init_submeshes(meshlink_handle_t *mesh) { + assert(!mesh->submeshes); mesh->submeshes = list_alloc((list_action_t)free_submesh); } @@ -61,6 +62,7 @@ void free_submesh(submesh_t *s) { static submesh_t *submesh_new(meshlink_handle_t *mesh, const char *submesh) { submesh_t *s = NULL; + assert(submesh); s = new_submesh(); s->name = xstrdup(submesh); @@ -70,6 +72,7 @@ static submesh_t *submesh_new(meshlink_handle_t *mesh, const char *submesh) { } submesh_t *create_submesh(meshlink_handle_t *mesh, const char *submesh) { + assert(submesh); submesh_t *s = NULL; if(0 == strcmp(submesh, CORE_MESH)) { @@ -99,6 +102,7 @@ submesh_t *create_submesh(meshlink_handle_t *mesh, const char *submesh) { } submesh_t *lookup_or_create_submesh(meshlink_handle_t *mesh, const char *submesh) { + assert(submesh); submesh_t *s = NULL; if(0 == strcmp(submesh, CORE_MESH)) { @@ -136,6 +140,8 @@ void submesh_del(meshlink_handle_t *mesh, submesh_t *s) { } submesh_t *lookup_submesh(struct meshlink_handle *mesh, const char *submesh_name) { + assert(submesh_name); + submesh_t *submesh = NULL; if(!mesh->submeshes) { -- 2.39.2