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.
char *buffer_prepare(buffer_t *buffer, size_t size) {
if(!buffer->data) {
+ assert(!buffer->maxlen);
+
buffer->maxlen = size;
buffer->data = xmalloc(size);
} else {
// 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;
// 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;
}
}
void buffer_clear(buffer_t *buffer) {
+ assert(!buffer->data == !buffer->maxlen);
+
free(buffer->data);
buffer->data = NULL;
buffer->maxlen = 0;
/// 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) {
}
static bool sync_path(const char *pathname) {
+ assert(pathname);
+
int fd = open(pathname, O_RDONLY);
if(fd < 0) {
/// 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;
/// 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;
/// 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;
}
}
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];
}
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];
/// 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;
}
}
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;
}
}
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);
/// 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)) {
/// 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);
/// 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;
/// 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;
}
/// 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;
}
}
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;
}
/// 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;
}
/// 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;
}
/// 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;
}
/// 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;
}
/// 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;
}
#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");
list_delete_list(mesh->connections);
}
- free_connection(mesh->everyone);
+ if(mesh->everyone) {
+ free_connection(mesh->everyone);
+ }
mesh->connections = NULL;
mesh->everyone = NULL;
}
void free_connection(connection_t *c) {
- if(!c) {
- return;
- }
+ assert(c);
sptps_stop(&c->sptps);
ecdsa_free(c->ecdsa);
}
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);
}
static int random_fd = -1;
void crypto_init(void) {
+ assert(random_fd == -1);
+
random_fd = open("/dev/urandom", O_RDONLY);
if(random_fd < 0) {
}
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) {
}
void randomize(void *out, size_t outlen) {
+ assert(outlen);
+
if(!CryptGenRandom(prov, outlen, out)) {
fprintf(stderr, "CryptGenRandom() failed\n");
abort();
}
static bool fstrwrite(const char *str, FILE *stream) {
+ assert(stream);
+
size_t len = strlen(str);
if(fwrite((void *)str, 1, len, stream) != len) {
}
bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream) {
+ assert(stream);
+
bool result = true;
pthread_mutex_lock(&(mesh->mesh_mutex));
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);
#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));
}
(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) {
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");
(void)server;
meshlink_handle_t *mesh = userdata;
- // asserts
- assert(mesh != NULL);
+ assert(mesh);
switch(state) {
case CATTA_SERVER_RUNNING:
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);
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);
meshlink_handle_t *mesh = userdata;
+ assert(mesh);
+
if(event != CATTA_RESOLVER_FOUND) {
catta_s_service_resolver_free(resolver);
return;
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);
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;
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);
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;
}
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;
}
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) {
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) {
}
edge_t *lookup_edge(node_t *from, node_t *to) {
+ assert(from);
+ assert(to);
+
edge_t v;
v.from = from;
}
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;
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) {
}
void io_del(event_loop_t *loop, io_t *io) {
- if(!io->cb) {
- return;
- }
+ assert(io->cb);
loop->deletion = true;
}
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);
}
}
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) {
}
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;
}
void signal_del(event_loop_t *loop, signal_t *sig) {
- if(!sig->cb) {
- return;
- }
+ assert(sig->cb);
loop->deletion = true;
}
bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) {
+ assert(mutex);
+
fd_set readable;
fd_set writable;
}
// 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);
}
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);
}
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
+#include <assert.h>
#ifdef HAVE_MINGW
#include <w32api.h>
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);
}
// 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;
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);
}
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);
}
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)) {
}
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;
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()");
}
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]) {
}
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;
}
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;
} /* 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);
#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;
}
// 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;
*/
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.
*/
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 */
}
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
}
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;
}
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)) {
}
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
}
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) {
}
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;
}
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];
}
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];
}
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;
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;
}
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;
}
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];
/* 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];
}
bool error_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
+ assert(request);
+ assert(*request);
+
int err;
char errorstring[MAX_STRING_SIZE];
(void)mesh;
(void)c;
(void)request;
+
+ assert(request);
+ assert(*request);
+
return false;
}
bool ping_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
(void)request;
+
+ assert(request);
+ assert(*request);
+
return send_pong(mesh, 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. */
/* 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) {
#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;
}
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;
/* 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;
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;
}
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 {
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 */
(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);
}
// 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);
}
static void warning(sptps_t *s, const char *format, ...) {
+ assert(format);
+
va_list ap;
va_start(ap, format);
sptps_log(s, 0, format, ap);
// 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) {
// 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();
#include "protocol.h"
void init_submeshes(meshlink_handle_t *mesh) {
+ assert(!mesh->submeshes);
mesh->submeshes = list_alloc((list_action_t)free_submesh);
}
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);
}
submesh_t *create_submesh(meshlink_handle_t *mesh, const char *submesh) {
+ assert(submesh);
submesh_t *s = NULL;
if(0 == strcmp(submesh, CORE_MESH)) {
}
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)) {
}
submesh_t *lookup_submesh(struct meshlink_handle *mesh, const char *submesh_name) {
+ assert(submesh_name);
+
submesh_t *submesh = NULL;
if(!mesh->submeshes) {