Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ add_executable(fastd
hkdf_sha256.c
fastd.c
iface.c
inotify.c
lex.c
log.c
options.c
Expand Down
170 changes: 123 additions & 47 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "method.h"
#include "peer.h"
#include "peer_group.h"
#include "inotify.h"
#include <generated/config.yy.h>

#include <dirent.h>
Expand Down Expand Up @@ -223,8 +224,23 @@ static bool has_peer_group_peer_dirs(const fastd_peer_group_t *group) {
return false;
}

static void add_peer(const char *name, fastd_peer_group_t *group, const char *dir) {
fastd_peer_t *peer = fastd_new0(fastd_peer_t);
peer->name = fastd_strdup(name);
peer->config_source_dir = dir;

if (!fastd_config_read(name, group, peer, 0)) {
fastd_peer_free(peer);
return;
}

fastd_peer_add(peer);
}

/** Reads and processes all peer definitions in the current directory (which must also be supplied as the argument) */
static void read_peer_dir(fastd_peer_group_t *group, const char *dir) {
fastd_inotify_add_config_dir(dir);

DIR *dirh = opendir(".");

if (dirh) {
Expand Down Expand Up @@ -256,16 +272,7 @@ static void read_peer_dir(fastd_peer_group_t *group, const char *dir) {
continue;
}

fastd_peer_t *peer = fastd_new0(fastd_peer_t);
peer->name = fastd_strdup(result->d_name);
peer->config_source_dir = dir;

if (!fastd_config_read(result->d_name, group, peer, 0)) {
fastd_peer_free(peer);
continue;
}

fastd_peer_add(peer);
add_peer(result->d_name, group, dir);
}

if (closedir(dirh) < 0)
Expand Down Expand Up @@ -639,44 +646,48 @@ static void peer_dirs_read_peer_group(fastd_peer_group_t *group) {
peer_dirs_read_peer_group(child);
}

/** Initializes the configured peers */
static void configure_peers(bool dirs_only) {
ctx.has_floating = false;
ctx.max_mtu = conf.mtu;
static void configure_peer(fastd_peer_t *peer, bool dirs_only) {
pr_info("Calling configure on peer: %P", peer);
if (peer->config_state == CONFIG_STATIC) {
/* The peer hasn't been touched since the last run of configure_peers(), so its definition must have disappeared */
fastd_peer_delete(peer);
return;
}

ssize_t i;
for (i = VECTOR_LEN(ctx.peers)-1; i >= 0; i--) {
fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
if (fastd_peer_is_dynamic(peer))
return;

if (peer->config_state == CONFIG_STATIC) {
/* The peer hasn't been touched since the last run of configure_peers(), so its definition must have disappeared */
fastd_peer_delete(peer);
continue;
}
if (peer->config_state != CONFIG_DISABLED && !conf.protocol->check_peer(peer))
peer->config_state = CONFIG_DISABLED;

if (fastd_peer_is_dynamic(peer))
continue;
if (peer->config_state == CONFIG_DISABLED) {
fastd_peer_reset(peer);
return;
}

if (peer->config_state != CONFIG_DISABLED && !conf.protocol->check_peer(peer))
peer->config_state = CONFIG_DISABLED;
if (fastd_peer_is_floating(peer))
ctx.has_floating = true;

if (peer->config_state == CONFIG_DISABLED) {
fastd_peer_reset(peer);
continue;
}
if (conf.mode != MODE_TAP && peer->mtu > ctx.max_mtu)
ctx.max_mtu = peer->mtu;

if (fastd_peer_is_floating(peer))
ctx.has_floating = true;
peer->config_state = CONFIG_STATIC;

if (conf.mode != MODE_TAP && peer->mtu > ctx.max_mtu)
ctx.max_mtu = peer->mtu;
if (!fastd_peer_is_established(peer)) {
if (peer->config_source_dir || !dirs_only)
fastd_peer_reset(peer);
}
}

peer->config_state = CONFIG_STATIC;
/** Initializes the configured peers */
static void configure_peers(bool dirs_only) {
ctx.has_floating = false;
ctx.max_mtu = conf.mtu;

if (!fastd_peer_is_established(peer)) {
if (peer->config_source_dir || !dirs_only)
fastd_peer_reset(peer);
}
ssize_t i;
for (i = VECTOR_LEN(ctx.peers)-1; i >= 0; i--) {
fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
configure_peer(peer, dirs_only);
}
}

Expand All @@ -685,24 +696,89 @@ void fastd_configure_peers(void) {
configure_peers(false);
}

void reset_peer_config_state(fastd_peer_t *peer) {
if (fastd_peer_is_dynamic(peer))
return;

/* Reset all peers' config states */
if (!peer->config_source_dir)
peer->config_state = CONFIG_NEW;
else if (peer->config_state == CONFIG_DISABLED)
peer->config_state = CONFIG_STATIC;
pr_info("Reset peer config state: %P", peer);
}

/** Refreshes the peer configurations from the configured peer dirs */
void fastd_config_load_peer_dirs(bool dirs_only) {
size_t i;
for (i = 0; i < VECTOR_LEN(ctx.peers); i++) {
fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
reset_peer_config_state(peer);
}

if (fastd_peer_is_dynamic(peer))
continue;
peer_dirs_read_peer_group(conf.peer_group);
configure_peers(true);
}

static fastd_peer_group_t *find_group_from_dir(fastd_peer_group_t *group, const char *conf_dir) {
fastd_string_stack_t *dir;
for (dir = group->peer_dirs; dir; dir = dir->next) {
if (!strcmp(dir->str, conf_dir))
return group;
}
if (group->children) {
find_group_from_dir(group->children, conf_dir);
}
if (group->next) {
find_group_from_dir(group->next, conf_dir);
}
return NULL;
}

/* Reset all peers' config states */
static fastd_peer_t *find_peer_by_name_and_dir(const char *dir, const char *name) {
int i;
for (i = 0; i < VECTOR_LEN(ctx.peers); i++) {
fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
if (!peer->config_source_dir)
peer->config_state = CONFIG_NEW;
else if (peer->config_state == CONFIG_DISABLED)
peer->config_state = CONFIG_STATIC;
continue;
if (!peer->name)
continue;
if (strcmp(peer->config_source_dir, dir))
continue;
if (strcmp(peer->name, name))
continue;
return peer;
}
return NULL;
}

peer_dirs_read_peer_group(conf.peer_group);
configure_peers(dirs_only);
void fastd_config_load_peer(const char *dir, const char *name) {
fastd_peer_group_t *group = find_group_from_dir(conf.peer_group, dir);
if (!group) {
pr_warn("Unable to find group for config %s in dir %s", name, dir);
return;
}

fastd_peer_t *peer = find_peer_by_name_and_dir(dir, name);
if (peer)
reset_peer_config_state(peer);

char *oldcwd = get_current_dir_name();
chdir(dir);
add_peer(name, group, dir);
if (chdir(oldcwd))
pr_error("can't chdir to `%s': %s", oldcwd, strerror(errno));
free(oldcwd);

peer = find_peer_by_name_and_dir(dir, name);
if (peer)
configure_peer(peer, false);
}

void fastd_config_delete_peer(const char *dir, const char *name) {
fastd_peer_t *peer = find_peer_by_name_and_dir(dir, name);
if (peer)
fastd_peer_delete(peer);
}

/** Frees all resources used by the global configuration */
Expand Down
2 changes: 2 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,7 @@ void fastd_configure(int argc, char *const argv[]);
void fastd_configure_peers(void);
void fastd_config_check(void);
void fastd_config_load_peer_dirs(bool dirs_only);
void fastd_config_load_peer(const char *dir, const char *name);
void fastd_config_delete_peer(const char *dir, const char *name);
bool fastd_config_single_iface(void);
bool fastd_config_persistent_ifaces(void);
2 changes: 2 additions & 0 deletions src/fastd.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include "fastd.h"
#include "async.h"
#include "inotify.h"
#include "config.h"
#include "crypto.h"
#include "peer.h"
Expand Down Expand Up @@ -539,6 +540,7 @@ static inline void init(int argc, char *argv[]) {

fastd_status_init();
fastd_async_init();
fastd_inotify_init();

fastd_socket_bind_all();

Expand Down
3 changes: 3 additions & 0 deletions src/fastd.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ struct fastd_context {

pthread_attr_t detached_thread; /**< pthread_attr_t for creating detached threads */

fastd_poll_fd_t inotify_fd; /**< The fd for the inotifier watching for config dir changes */
VECTOR(fastd_inotify_watch_descriptor_t *) inotify_wd; /**< A map from watch descriptor number to directory name */

#ifdef __ANDROID__
int android_ctrl_sock_fd; /**< The unix domain socket for communicating with Android GUI */
#endif
Expand Down
Loading