# #
#############################################################################*/
+#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include "address.h"
// Create a new configuration
r = nw_config_create(config, f);
-ERROR:
if (f)
fclose(f);
return nw_config_set(config, key, value ? "true" : "false");
}
+/*
+ Directory
+*/
+
+struct nw_configd {
+ int nrefs;
+
+ char path[PATH_MAX];
+ int fd;
+};
+
+static void nw_configd_free(nw_configd* dir) {
+ if (dir->fd >= 0)
+ close(dir->fd);
+
+ free(dir);
+}
+
+static int __nw_configd_create(nw_configd** dir, int fd, const char* path) {
+ nw_configd* d = NULL;
+ int r;
+
+ // Allocate a new object
+ d = calloc(1, sizeof(*d));
+ if (!d)
+ return -errno;
+
+ // Initialize the reference counter
+ d->nrefs = 1;
+
+ // Store the file descriptor
+ d->fd = dup(fd);
+ if (d->fd < 0) {
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Store path
+ if (path) {
+ r = nw_string_set(d->path, path);
+ if (r < 0)
+ goto ERROR;
+ }
+
+ *dir = d;
+ return 0;
+
+ERROR:
+ nw_configd_free(d);
+ return r;
+}
+
+int nw_configd_create(nw_configd** dir, const char* path) {
+ int fd;
+
+ // Open the directory
+ fd = open(path, O_DIRECTORY);
+ if (fd < 0) {
+ ERROR("Could not open %s: %m\n", path);
+ return -errno;
+ }
+
+ return __nw_configd_create(dir, fd, path);
+}
+
+nw_configd* nw_configd_ref(nw_configd* dir) {
+ dir->nrefs++;
+
+ return dir;
+}
+
+nw_configd* nw_configd_unref(nw_configd* dir) {
+ if (--dir->nrefs > 0)
+ return dir;
+
+ nw_configd_free(dir);
+ return NULL;
+}
+
+static int nw_configd_open(nw_configd* dir, const char* path, int flags) {
+ return openat(dir->fd, path, flags);
+}
+
+FILE* nw_configd_fopen(nw_configd* dir, const char* path, const char* mode) {
+ int fd;
+
+ // Open file
+ fd = nw_configd_open(dir, path, 0);
+ if (fd < 0)
+ return NULL;
+
+ // Return a file handle
+ return fdopen(fd, mode);
+}
+
+int nw_configd_open_config(nw_config** config, nw_configd* dir, const char* path) {
+ FILE* f = NULL;
+ int r;
+
+ // Open the file
+ f = nw_configd_fopen(dir, path, "r");
+ if (!f)
+ return -errno;
+
+ // Create configuration
+ r = nw_config_create(config, f);
+ if (r < 0)
+ goto ERROR;
+
+ERROR:
+ if (f)
+ fclose(f);
+
+ return r;
+}
+
+int nw_configd_unlink(nw_configd* dir, const char* path, int flags) {
+ return unlinkat(dir->fd, path, flags);
+}
+
+nw_configd* nw_configd_descend(nw_configd* dir, const char* path) {
+ nw_configd* d = NULL;
+ char p[PATH_MAX];
+ int fd = -1;
+ int r;
+
+ // Join paths
+ r = nw_path_join(p, dir->path, path);
+ if (r < 0)
+ goto ERROR;
+
+ // Open directory
+ fd = nw_configd_open(dir, path, O_DIRECTORY);
+ if (fd < 0) {
+ ERROR("Could not open %s: %m\n", p);
+ goto ERROR;
+ }
+
+ // Create a new config directory object
+ r = __nw_configd_create(&d, fd, p);
+ if (r < 0)
+ goto ERROR;
+
+ERROR:
+ if (fd >= 0)
+ close(fd);
+
+ return d;
+}
+
+int nw_configd_walk(nw_configd* dir, nw_configd_walk_callback callback, void* data) {
+ FILE* f = NULL;
+ DIR* d = NULL;
+ struct dirent* e = NULL;
+ int r;
+
+ // Re-open the directory
+ d = fdopendir(dir->fd);
+ if (!d) {
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Walk trough everything
+ for (;;) {
+ // Read the next entry
+ e = readdir(d);
+ if (!e)
+ break;
+
+ // Skip anything that is not a regular file
+ if (e->d_type != DT_REG)
+ continue;
+
+ // Skip hidden files
+ if (e->d_name[0] == '.')
+ continue;
+
+ // Open the file
+ f = nw_configd_fopen(dir, e->d_name, "r");
+ if (!f) {
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Call the callback
+ r = callback(e, f, data);
+ fclose(f);
+
+ if (r < 0)
+ goto ERROR;
+ }
+
+ r = 0;
+
+ERROR:
+ if (d)
+ closedir(d);
+
+ return r;
+}
+
/*
Options
*/
#ifndef NETWORKD_CONFIG_H
#define NETWORKD_CONFIG_H
+#include <dirent.h>
#include <stdio.h>
#define NETWORK_CONFIG_KEY_MAX_LENGTH 128
int nw_config_get_bool(nw_config* config, const char* key);
int nw_config_set_bool(nw_config* config, const char* key, const int value);
+/*
+ Directory
+*/
+
+typedef struct nw_configd nw_configd;
+
+int nw_configd_create(nw_configd** dir, const char* path);
+
+nw_configd* nw_configd_ref(nw_configd* dir);
+nw_configd* nw_configd_unref(nw_configd* dir);
+
+FILE* nw_configd_fopen(nw_configd* dir, const char* path, const char* mode);
+int nw_configd_open_config(nw_config** config, nw_configd* dir, const char* path);
+int nw_configd_unlink(nw_configd* dir, const char* path, int flags);
+
+nw_configd* nw_configd_descend(nw_configd* dir, const char* path);
+
+typedef int (*nw_configd_walk_callback)(struct dirent* entry, FILE* f, void* data);
+
+int nw_configd_walk(nw_configd* dir, nw_configd_walk_callback callback, void* data);
+
/*
Options
*/
int nrefs;
// Configuration
- int configfd;
+ nw_configd* configd;
nw_config* config;
// Event Loop
*/
static int nw_daemon_config_open(nw_daemon* daemon, const char* path) {
- // Open the directory
- daemon->configfd = open(path, O_DIRECTORY);
- if (daemon->configfd < 0) {
- ERROR("Could not open %s: %m\n", path);
- return -errno;
- }
-
- return 0;
-}
-
-FILE* nw_daemon_config_fopen(nw_daemon* daemon, const char* path, const char* mode) {
- // Open the file
- int fd = openat(daemon->configfd, path, 0);
- if (fd < 0) {
- ERROR("Could not open configuration file %s: %m\n", path);
- return NULL;
- }
-
- // Return a file handle
- return fdopen(fd, mode);
-}
+ int r;
-DIR* nw_daemon_config_opendir(nw_daemon* daemon, const char* path) {
- int fd = openat(daemon->configfd, path, O_DIRECTORY);
- if (fd < 0) {
- ERROR("Could not open configuration directory %s: %m\n", path);
- return NULL;
- }
+ // Open the configuration directory
+ r = nw_configd_create(&daemon->configd, path);
+ if (r < 0)
+ return r;
- return fdopendir(fd);
+ return 0;
}
static int nw_daemon_parse_argv(nw_daemon* daemon, int argc, char* argv[]) {
}
static int nw_daemon_load_config(nw_daemon* daemon) {
- FILE* f = NULL;
int r;
// If no configuration path has been opened yet, we will open something
- if (!daemon->configfd) {
+ if (!daemon->configd) {
r = nw_daemon_config_open(daemon, CONFIG_DIR);
if (r < 0)
- goto ERROR;
+ return r;
}
// Open the configuration file
- f = nw_daemon_config_fopen(daemon, "settings", "r");
- if (!f) {
- r = -errno;
- goto ERROR;
- }
-
- // Create configuration
- r = nw_config_create(&daemon->config, f);
- if (r < 0)
- goto ERROR;
-
-ERROR:
- if (f)
- fclose(f);
-
- return r;
+ return nw_configd_open_config(&daemon->config, daemon->configd, "settings");
}
static int nw_start_device_monitor(nw_daemon* daemon) {
// Cleanup common objects
nw_daemon_cleanup(daemon);
- if (daemon->configfd > 0)
- close(daemon->configfd);
+ if (daemon->configd)
+ nw_configd_unref(daemon->configd);
if (daemon->stats_collector_event)
sd_event_source_unref(daemon->stats_collector_event);
if (daemon->bus)
return 0;
}
+nw_configd* nw_daemon_configd(nw_daemon* daemon, const char* path) {
+ if (!daemon->configd)
+ return NULL;
+
+ if (path)
+ return nw_configd_descend(daemon->configd, path);
+
+ return nw_configd_ref(daemon->configd);
+}
+
/*
Bus
*/
typedef struct nw_daemon nw_daemon;
+#include "config.h"
#include "link.h"
#include "links.h"
#include "port.h"
int nw_daemon_save(nw_daemon* daemon);
-/*
- Configuration
-*/
-FILE* nw_daemon_config_fopen(nw_daemon* daemon, const char* path, const char* mode);
-DIR* nw_daemon_config_opendir(nw_daemon* daemon, const char* path);
+nw_configd* nw_daemon_configd(nw_daemon* daemon, const char* path);
/*
Bus
return r;
}
-int nw_port_open(nw_port** port, nw_daemon* daemon, const char* name) {
+int nw_port_open(nw_port** port, nw_daemon* daemon, const char* name, FILE* f) {
nw_config* config = NULL;
- FILE* f = NULL;
- char path[PATH_MAX];
int r;
- // Make path
- r = nw_string_format(path, "ports/%s", name);
- if (r < 0)
- goto ERROR;
-
- // Open the configuration file
- f = nw_daemon_config_fopen(daemon, path, "r");
- if (!f) {
- r = -errno;
- goto ERROR;
- }
-
// Initialize the configuration
r = nw_config_create(&config, f);
if (r < 0)
// Fetch the type
const char* type = nw_config_get(config, "TYPE");
if (!type) {
- ERROR("Port configuration %s has no TYPE\n", path);
+ ERROR("Port %s has no TYPE\n", name);
r = -ENOTSUP;
goto ERROR;
}
ERROR:
if (config)
nw_config_unref(config);
- if (f)
- fclose(f);
return r;
}
}
int nw_port_destroy(nw_port* port) {
+ nw_configd* configd = NULL;
int r;
DEBUG("Destroying port %s\n", port->name);
// Destroy the physical link (if exists)
if (port->link) {
r = nw_link_destroy(port->link);
- if (r)
- return r;
+ if (r < 0)
+ goto ERROR;
}
// Dereference the port from other ports
r = nw_daemon_ports_walk(port->daemon, __nw_port_drop_port, port);
- if (r)
- return r;
+ if (r < 0)
+ goto ERROR;
// Dereference the port from other zones
r = nw_daemon_zones_walk(port->daemon, __nw_zone_drop_port, port);
- if (r)
- return r;
+ if (r < 0)
+ goto ERROR;
- // Destroy the configuration
- r = nw_config_destroy(port->config);
- if (r)
- return r;
+ // Fetch the configuration directory
+ configd = nw_daemon_configd(port->daemon, "ports");
+ if (configd) {
+ r = nw_configd_unlink(configd, port->name, 0);
+ if (r < 0)
+ goto ERROR;
+ }
- return 0;
+ERROR:
+ if (configd)
+ nw_configd_unref(configd);
+
+ return r;
}
int __nw_port_drop_port(nw_daemon* daemon, nw_port* port, void* data) {
}
int nw_port_save(nw_port* port) {
- char path[PATH_MAX];
+ nw_configd* configd = NULL;
FILE* f = NULL;
int r;
- // Compose path
- r = nw_string_format(path, "ports/%s", port->name);
- if (r < 0)
- return r;
+ // Fetch configuration directory
+ configd = nw_daemon_configd(port->daemon, "ports");
+ if (!configd) {
+ r = -errno;
+ goto ERROR;
+ }
// Open file
- f = nw_daemon_config_fopen(port->daemon, path, "w");
+ f = nw_configd_fopen(configd, port->name, "w");
if (!f) {
r = -errno;
goto ERROR;
goto ERROR;
ERROR:
+ if (configd)
+ nw_configd_unref(configd);
if (f)
fclose(f);
if (r)
int nw_port_create(nw_port** port, nw_daemon* daemon,
const nw_port_type_id_t type, const char* name, nw_config* config);
-int nw_port_open(nw_port** port, nw_daemon* daemon, const char* name);
+int nw_port_open(nw_port** port, nw_daemon* daemon, const char* name, FILE* f);
nw_port* nw_port_ref(nw_port* port);
nw_port* nw_port_unref(nw_port* port);
return 0;
}
-static int nw_ports_enumerate_port(nw_ports* ports, const char* name) {
+static int __nw_ports_enumerate(struct dirent* entry, FILE* f, void* data) {
nw_port* port = NULL;
int r;
+ nw_ports* ports = (nw_ports*)data;
+
// Create a new port
- r = nw_port_open(&port, ports->daemon, name);
+ r = nw_port_open(&port, ports->daemon, entry->d_name, f);
if (r < 0 || r == 1)
goto ERROR;
}
int nw_ports_enumerate(nw_ports* ports) {
- DIR* d = NULL;
- struct dirent* entry = NULL;
+ nw_configd* configd = NULL;
int r;
- // Open the ports directory
- d = nw_daemon_config_opendir(ports->daemon, "ports");
- if (!d) {
- switch (errno) {
- case ENOENT:
- return 0;
-
- default:
- return -errno;
- }
- }
-
- for (;;) {
- // Read the next entry
- entry = readdir(d);
- if (!entry)
- break;
-
- // Skip anything that is not a regular file
- if (entry->d_type != DT_REG)
- continue;
+ // Fetch ports configuration directory
+ configd = nw_daemon_configd(ports->daemon, "ports");
+ if (!configd)
+ return 0;
- // Skip hidden files
- if (entry->d_name[0] == '.')
- continue;
+ // Walk through all files
+ r = nw_configd_walk(configd, __nw_ports_enumerate, ports);
- // Enumerate the port
- r = nw_ports_enumerate_port(ports, entry->d_name);
- if (r < 0)
- goto ERROR;
- }
-
-ERROR:
- if (d)
- closedir(d);
+ // Cleanup
+ nw_configd_unref(configd);
return r;
}
#include "string.h"
#include "zone.h"
+static const nw_string_table_t nw_zone_type_id[] = {
+ { -1, NULL },
+};
+
+NW_STRING_TABLE_LOOKUP(nw_zone_type_id_t, nw_zone_type_id)
+
struct nw_zone {
nw_daemon* daemon;
int nrefs;
nw_config *config;
};
-#define nw_zone_path(zone, path, format, ...) \
- __nw_zone_path(zone, path, sizeof(path), format, __VA_ARGS__)
-
-static int __nw_zone_path(nw_zone* zone, char* p, const size_t length,
- const char* format, ...) {
- char prefix[NAME_MAX];
- char suffix[NAME_MAX];
- va_list args;
- int r;
-
- // Format the prefix
- r = nw_string_format(prefix, "%s/zones/%s", CONFIG_DIR, zone->name);
- if (r)
- return r;
-
- // Format the suffix
- va_start(args, format);
- r = nw_string_vformat(suffix, format, args);
- va_end(args);
- if (r)
- return r;
-
- // Join the two parts together
- return __nw_path_join(p, length, prefix, suffix);
-}
-
static void nw_zone_free(nw_zone* zone) {
if (zone->link)
nw_link_unref(zone->link);
static int nw_zone_setup(nw_zone* zone) {
nw_link* link = NULL;
- char path[PATH_MAX];
- int r;
+ int r = 0;
// Find the link
link = nw_daemon_get_link_by_name(zone->daemon, zone->name);
goto ERROR;
}
-#if 0
- // Compose the path to the main configuration file
- r = nw_zone_path(zone, path, "%s", "settings");
- if (r)
- goto ERROR;
-
- // Initialize the configuration
- r = nw_config_create(&zone->config, path);
- if (r)
- goto ERROR;
-#endif
-
ERROR:
if (link)
nw_link_unref(link);
return r;
}
-int nw_zone_create(nw_zone** zone, nw_daemon* daemon, const char* name) {
+int nw_zone_create(nw_zone** zone, nw_daemon* daemon, const nw_zone_type_id_t type,
+ const char* name, nw_config* config) {
+ nw_zone* z = NULL;
int r;
// Allocate a new object
- nw_zone* z = calloc(1, sizeof(*z));
+ z = calloc(1, sizeof(*z));
if (!z)
- return 1;
+ return -errno;
// Store a reference to the daemon
z->daemon = nw_daemon_ref(daemon);
if (r)
goto ERROR;
+ // Copy the configuration
+ r = nw_config_copy(config, &z->config);
+ if (r < 0)
+ goto ERROR;
+
// Setup the zone
r = nw_zone_setup(z);
if (r)
return r;
}
+int nw_zone_open(nw_zone** zone, nw_daemon* daemon, const char* name, FILE* f) {
+ nw_config* config = NULL;
+ int r;
+
+ // Initialize the configuration
+ r = nw_config_create(&config, f);
+ if (r < 0)
+ goto ERROR;
+
+ // Fetch the type
+ const char* type = nw_config_get(config, "TYPE");
+ if (!type) {
+ ERROR("Zone %s has no TYPE\n", name);
+ r = -ENOTSUP;
+ goto ERROR;
+ }
+
+ // Create a new zone
+ r = nw_zone_create(zone, daemon, nw_zone_type_id_from_string(type), name, config);
+ if (r < 0)
+ goto ERROR;
+
+ERROR:
+ if (config)
+ nw_config_unref(config);
+
+ return r;
+}
+
nw_zone* nw_zone_ref(nw_zone* zone) {
zone->nrefs++;
}
int nw_zone_save(nw_zone* zone) {
- char path[PATH_MAX];
+ nw_configd* configd = NULL;
FILE* f = NULL;
int r;
- // Compose path
- r = nw_string_format(path, "zones/%s/settings", zone->name);
- if (r < 0)
+ // Fetch configuration directory
+ configd = nw_daemon_configd(zone->daemon, "zones");
+ if (!configd) {
+ r = -errno;
goto ERROR;
+ }
// Open file
- f = nw_daemon_config_fopen(zone->daemon, path, "w");
+ f = nw_configd_fopen(configd, zone->name, "w");
if (!f) {
r = -errno;
goto ERROR;
}
+ // Write out the configuration
+ r = nw_config_options_write(zone->config);
+ if (r < 0)
+ goto ERROR;
+
// Write the configuration
r = nw_config_write(zone->config, f);
- if (r)
+ if (r < 0)
goto ERROR;
ERROR:
+ if (configd)
+ nw_configd_unref(configd);
if (f)
fclose(f);
+ if (r)
+ ERROR("Could not save configuration for zone %s: %s\n", zone->name, strerror(-r));
return r;
}
typedef struct nw_zone nw_zone;
+typedef enum nw_zone_type_id {
+ __EMPTY
+} nw_zone_type_id_t;
+
#include <linux/if_link.h>
+#include "config.h"
#include "daemon.h"
-int nw_zone_create(nw_zone** zone, nw_daemon* daemon, const char* name);
+int nw_zone_create(nw_zone** zone, nw_daemon* daemon, const nw_zone_type_id_t type,
+ const char* name, nw_config* config);
+int nw_zone_open(nw_zone** zone, nw_daemon* daemon, const char* name, FILE* f);
nw_zone* nw_zone_ref(nw_zone* zone);
nw_zone* nw_zone_unref(nw_zone* zone);
return 0;
}
-static int __nw_zones_enumerate(const char* path, const struct stat* s, void* data) {
+static int __nw_zones_enumerate(struct dirent* entry, FILE* f, void* data) {
nw_zone* zone = NULL;
int r;
nw_zones* zones = (nw_zones*)data;
- // Skip anything that isn't a directory
- if (!S_ISDIR(s->st_mode))
- return 0;
-
- // Find the basename of the file
- const char* name = nw_path_basename(path);
-
- // Break on invalid paths
- if (!name)
- return 0;
-
- // Skip any hidden files
- if (*name == '.')
- return 0;
-
// Create a new zone
- r = nw_zone_create(&zone, zones->daemon, name);
- if (r)
+ r = nw_zone_open(&zone, zones->daemon, entry->d_name, f);
+ if (r < 0 || r == 1)
goto ERROR;
// Add the zone to the list
}
int nw_zones_enumerate(nw_zones* zones) {
- return nw_ftw(ZONE_CONFIG_DIR, ZONE_CONFIG_DIR "/*", __nw_zones_enumerate, zones);
+ nw_configd* configd = NULL;
+ int r;
+
+ // Fetch zones configuration directory
+ configd = nw_daemon_configd(zones->daemon, "zones");
+ if (!configd)
+ return 0;
+
+ // Walk through all files
+ r = nw_configd_walk(configd, __nw_zones_enumerate, zones);
+
+ // Cleanup
+ nw_configd_unref(configd);
+
+ return r;
}
size_t nw_zones_num(nw_zones* zones) {