]> git.ipfire.org Git - people/ms/network.git/commitdiff
ports: Refactor enumerating ports
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 9 Jun 2023 09:29:01 +0000 (09:29 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 9 Jun 2023 09:29:01 +0000 (09:29 +0000)
This entails a little rewrite how we deal with where configuration files
are stored.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/networkd/config.c
src/networkd/config.h
src/networkd/daemon.c
src/networkd/daemon.h
src/networkd/port.c
src/networkd/port.h
src/networkd/ports.c
src/networkd/zone.c

index b7f3f7220e8f2835343374ce3e4495131fc4861e..3d444c41c19e338178de722fce438ef27f6633e1 100644 (file)
@@ -53,9 +53,6 @@ struct nw_config_option {
 struct nw_config {
        int nrefs;
 
-       // The path to the configuration file
-       char path[PATH_MAX];
-
        STAILQ_HEAD(config_entries, nw_config_entry) entries;
 
        // Options
@@ -118,7 +115,7 @@ static void nw_config_free(nw_config* config) {
        free(config);
 }
 
-int nw_config_create(nw_config** config, const char* path) {
+int nw_config_create(nw_config** config, FILE* f) {
        int r;
 
        nw_config* c = calloc(1, sizeof(*c));
@@ -134,15 +131,10 @@ int nw_config_create(nw_config** config, const char* path) {
        // Initialise options
        STAILQ_INIT(&c->options);
 
-       // Store the path
-       if (path) {
-               r = nw_string_set(c->path, path);
-               if (r)
-                       goto ERROR;
-
-               // Try to read the configuration from path
-               r = nw_config_read(c);
-               if (r)
+       // Read configuration
+       if (f) {
+               r = nw_config_read(c, f);
+               if (r < 0)
                        goto ERROR;
        }
 
@@ -156,6 +148,25 @@ ERROR:
        return r;
 }
 
+int nw_config_open(nw_config** config, const char* path) {
+       FILE* f = NULL;
+       int r;
+
+       // Open path
+       f = fopen(path, "r");
+       if (!f)
+               return -errno;
+
+       // Create a new configuration
+       r = nw_config_create(config, f);
+
+ERROR:
+       if (f)
+               fclose(f);
+
+       return r;
+}
+
 nw_config* nw_config_ref(nw_config* config) {
        config->nrefs++;
 
@@ -170,17 +181,6 @@ nw_config* nw_config_unref(nw_config* config) {
        return NULL;
 }
 
-int nw_config_destroy(nw_config* config) {
-       int r;
-
-       // Drop all entries
-       r = nw_config_flush(config);
-       if (r)
-               return r;
-
-       return unlink(config->path);
-}
-
 int nw_config_copy(nw_config* config, nw_config** copy) {
        struct nw_config_entry* entry = NULL;
        nw_config* c = NULL;
@@ -208,13 +208,6 @@ ERROR:
        return r;
 }
 
-const char* nw_config_path(nw_config* config) {
-       if (*config->path)
-               return config->path;
-
-       return NULL;
-}
-
 int nw_config_flush(nw_config* config) {
        struct nw_config_entry* entry = NULL;
 
@@ -229,7 +222,7 @@ int nw_config_flush(nw_config* config) {
        return 0;
 }
 
-int nw_config_readf(nw_config* config, FILE* f) {
+int nw_config_read(nw_config* config, FILE* f) {
        char* line = NULL;
        size_t length = 0;
        int r;
@@ -275,39 +268,7 @@ int nw_config_readf(nw_config* config, FILE* f) {
        return r;
 }
 
-int nw_config_read(nw_config* config) {
-       FILE* f = NULL;
-       int r;
-
-       // We cannot read if path is not set
-       if (!*config->path) {
-               errno = ENOTSUP;
-               return 1;
-       }
-
-       // Open the file
-       f = fopen(config->path, "r");
-       if (!f) {
-               // Silently ignore if the file does not exist
-               if (errno == ENOENT)
-                       return 0;
-
-               ERROR("Could not read configuration file %s: %m\n", config->path);
-               r = 1;
-               goto ERROR;
-       }
-
-       // Read from file
-       r = nw_config_readf(config, f);
-
-ERROR:
-       if (f)
-               fclose(f);
-
-       return r;
-}
-
-static int nw_config_writef(nw_config* config, FILE* f) {
+int nw_config_write(nw_config* config, FILE* f) {
        struct nw_config_entry* entry = NULL;
        int r;
 
@@ -327,32 +288,6 @@ static int nw_config_writef(nw_config* config, FILE* f) {
        return 0;
 }
 
-int nw_config_write(nw_config* config) {
-       int r;
-
-       // We cannot write if path is not set
-       if (!*config->path) {
-               errno = ENOTSUP;
-               return 1;
-       }
-
-       FILE* f = fopen(config->path, "w");
-       if (!f) {
-               ERROR("Failed to open %s for writing: %m\n", config->path);
-               r = 1;
-               goto ERROR;
-       }
-
-       // Write configuration
-       r = nw_config_writef(config, f);
-
-ERROR:
-       if (f)
-               fclose(f);
-
-       return r;
-}
-
 static struct nw_config_entry* nw_config_find(nw_config* config, const char* key) {
        struct nw_config_entry* entry = NULL;
 
index d532da33ad71e813b1cf1a67cf466ca4ff2ed021..b25d05e6e1b7480bfff9d81c4c0b4bc9b37d49fe 100644 (file)
 
 typedef struct nw_config nw_config;
 
-int nw_config_create(nw_config** config, const char* path);
+int nw_config_create(nw_config** config, FILE* f);
+int nw_config_open(nw_config** config, const char* path);
 
 nw_config* nw_config_ref(nw_config* config);
 nw_config* nw_config_unref(nw_config* config);
 
-int nw_config_destroy(nw_config* config);
 int nw_config_copy(nw_config* config, nw_config** copy);
 
-const char* nw_config_path(nw_config* config);
-
 int nw_config_flush(nw_config* config);
 
-int nw_config_readf(nw_config* config, FILE* f);
-int nw_config_read(nw_config* config);
-int nw_config_write(nw_config* config);
+int nw_config_read(nw_config* config, FILE* f);
+int nw_config_write(nw_config* config, FILE* f);
 
 int nw_config_del(nw_config* config, const char* key);
 
index f0ef4aa31ef1aa2db70c812ee9fba3bc36b4964d..a62e343fdef1318f07c7a9e69e2714ef236a77a2 100644 (file)
@@ -113,7 +113,7 @@ static int nw_daemon_config_open(nw_daemon* daemon, const char* path) {
        return 0;
 }
 
-static FILE* nw_daemon_config_fopen(nw_daemon* daemon, const char* path, const char* mode) {
+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) {
@@ -125,6 +125,16 @@ static FILE* nw_daemon_config_fopen(nw_daemon* daemon, const char* path, const c
        return fdopen(fd, mode);
 }
 
+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;
+       }
+
+       return fdopendir(fd);
+}
+
 static int nw_daemon_parse_argv(nw_daemon* daemon, int argc, char* argv[]) {
        enum {
                ARG_CONFIG,
@@ -221,12 +231,7 @@ static int nw_daemon_load_config(nw_daemon* daemon) {
        }
 
        // Create configuration
-       r = nw_config_create(&daemon->config, NULL);
-       if (r < 0)
-               goto ERROR;
-
-       // Parse configuration
-       r = nw_config_readf(daemon->config, f);
+       r = nw_config_create(&daemon->config, f);
        if (r < 0)
                goto ERROR;
 
@@ -615,10 +620,12 @@ int nw_daemon_save(nw_daemon* daemon) {
 
        DEBUG("Saving configuration...\n");
 
+#if 0
        // Save settings
-       r = nw_config_write(daemon->config);
+       r = nw_config_write(daemon->config, f);
        if (r)
                return r;
+#endif
 
        // Save ports
        r = nw_ports_save(daemon->ports);
index 8653af386fb5e07e62f567e79adfebbce626caa8..b03086c873b5f0ae7a6468040091cd326ecde1a7 100644 (file)
@@ -21,6 +21,9 @@
 #ifndef NETWORKD_DAEMON_H
 #define NETWORKD_DAEMON_H
 
+#include <dirent.h>
+#include <stdio.h>
+
 #include <systemd/sd-bus.h>
 #include <systemd/sd-netlink.h>
 
@@ -44,6 +47,12 @@ int nw_daemon_reload(nw_daemon* daemon);
 
 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);
+
 /*
        Bus
 */
index fb5d418911193527367cb10b5b41f9a1b6377f86..7d654e3c9bd59afc5593b9136262172b7afc9551 100644 (file)
@@ -147,7 +147,7 @@ int nw_port_create(nw_port** port, nw_daemon* daemon,
        // Allocate a new object
        nw_port* p = calloc(1, sizeof(*p));
        if (!p)
-               return 1;
+               return -errno;
 
        // Store a reference to the daemon
        p->daemon = nw_daemon_ref(daemon);
@@ -172,17 +172,17 @@ int nw_port_create(nw_port** port, nw_daemon* daemon,
 
        // Store the name
        r = nw_string_set(p->name, name);
-       if (r)
+       if (r < 0)
                goto ERROR;
 
        // Copy the configuration
        r = nw_config_copy(config, &p->config);
-       if (r)
+       if (r < 0)
                goto ERROR;
 
        // Setup the port
        r = nw_port_setup(p);
-       if (r)
+       if (r < 0)
                goto ERROR;
 
        // Validate the configuration
@@ -210,32 +210,47 @@ ERROR:
        return r;
 }
 
-int nw_port_create_from_config(nw_port** port, nw_daemon* daemon,
-               const char* name, const char* path) {
+int nw_port_open(nw_port** port, nw_daemon* daemon, const char* name) {
        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, path);
-       if (r)
+       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("Port configuration %s has no TYPE\n", path);
-               r = 1;
+               r = -ENOTSUP;
                goto ERROR;
        }
 
        // Create a new port
        r = nw_port_create(port, daemon, nw_port_type_id_from_string(type), name, config);
-       if (r)
+       if (r < 0)
                goto ERROR;
 
 ERROR:
        if (config)
                nw_config_unref(config);
+       if (f)
+               fclose(f);
 
        return r;
 }
@@ -316,24 +331,39 @@ int __nw_port_drop_port(nw_daemon* daemon, nw_port* port, void* data) {
 }
 
 int nw_port_save(nw_port* port) {
+       char path[PATH_MAX];
+       FILE* f = NULL;
        int r;
 
+       // Compose path
+       r = nw_string_format(path, "ports/%s", port->name);
+       if (r < 0)
+               return r;
+
+       // Open file
+       f = nw_daemon_config_fopen(port->daemon, path, "w");
+       if (!f) {
+               r = -errno;
+               goto ERROR;
+       }
+
        // Write out the configuration
        r = nw_config_options_write(port->config);
        if (r < 0)
                goto ERROR;
 
        // Write the configuration
-       r = nw_config_write(port->config);
-       if (r)
-               return r;
-
-       return 0;
+       r = nw_config_write(port->config, f);
+       if (r < 0)
+               goto ERROR;
 
 ERROR:
-       ERROR("Could not save configuration for port %s: %s\n", port->name, strerror(-r));
+       if (f)
+               fclose(f);
+       if (r)
+               ERROR("Could not save configuration for port %s: %s\n", port->name, strerror(-r));
 
-       return 1;
+       return r;
 }
 
 const char* nw_port_name(nw_port* port) {
index 7c2e43668e282bf15ebbe2750b8b0aada68ea2a1..efa2fdbe9b7d68a29b6033634e613f72198e6810 100644 (file)
@@ -95,8 +95,7 @@ struct nw_port {
 
 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_create_from_config(nw_port** port, nw_daemon* daemon,
-       const char* name, const char* path);
+int nw_port_open(nw_port** port, nw_daemon* daemon, const char* name);
 
 nw_port* nw_port_ref(nw_port* port);
 nw_port* nw_port_unref(nw_port* port);
index 65545e813c12050b832134c8b9384925c80387ab..761e564a53b30c7fa7109ac4f889311c0f3bde4d 100644 (file)
@@ -18,6 +18,7 @@
 #                                                                             #
 #############################################################################*/
 
+#include <dirent.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/queue.h>
@@ -129,43 +130,14 @@ static int nw_ports_add_port(nw_ports* ports, nw_port* port) {
        return 0;
 }
 
-static int __nw_ports_enumerate(const char* path, const struct stat* s, void* data) {
+static int nw_ports_enumerate_port(nw_ports* ports, const char* name) {
        nw_port* port = NULL;
        int r;
 
-       nw_ports* ports = (nw_ports*)data;
-
-       // Skip anything that isn't a regular file
-       if (!S_ISREG(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 port
-       r = nw_port_create_from_config(&port, ports->daemon, name, path);
-       switch (r) {
-               // All okay
-               case 0:
-                       break;
-
-               // Invalid configuration
-               case 1:
-                       ERROR("Could not open port %s\n", name);
-                       r = 0;
-                       goto ERROR;
-
-               default:
-                       goto ERROR;
-       }
+       r = nw_port_open(&port, ports->daemon, name);
+       if (r < 0 || r == 1)
+               goto ERROR;
 
        // Add the port to the list
        r = nw_ports_add_port(ports, port);
@@ -180,7 +152,47 @@ ERROR:
 }
 
 int nw_ports_enumerate(nw_ports* ports) {
-       return nw_ftw(PORT_CONFIG_DIR, PORT_CONFIG_DIR "/*", __nw_ports_enumerate, ports);
+       DIR* d = NULL;
+       struct dirent* entry = 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;
+
+               // Skip hidden files
+               if (entry->d_name[0] == '.')
+                       continue;
+
+               // Enumerate the port
+               r = nw_ports_enumerate_port(ports, entry->d_name);
+               if (r < 0)
+                       goto ERROR;
+       }
+
+ERROR:
+       if (d)
+               closedir(d);
+
+       return r;
 }
 
 nw_port* nw_ports_get_by_name(nw_ports* ports, const char* name) {
index 9f5b7f8cba45bfbb6afbe2bbfe1a9aa7e39216e9..cc5fdaf5bdcc903334529495ead9c4df68847290 100644 (file)
@@ -120,6 +120,7 @@ static int nw_zone_setup(nw_zone* zone) {
                        goto ERROR;
        }
 
+#if 0
        // Compose the path to the main configuration file
        r = nw_zone_path(zone, path, "%s", "settings");
        if (r)
@@ -129,6 +130,7 @@ static int nw_zone_setup(nw_zone* zone) {
        r = nw_config_create(&zone->config, path);
        if (r)
                goto ERROR;
+#endif
 
 ERROR:
        if (link)
@@ -193,13 +195,32 @@ int __nw_zone_drop_port(nw_daemon* daemon, nw_zone* zone, void* data) {
 }
 
 int nw_zone_save(nw_zone* zone) {
+       char path[PATH_MAX];
+       FILE* f = NULL;
        int r;
 
-       r = nw_config_write(zone->config);
+       // Compose path
+       r = nw_string_format(path, "zones/%s/settings", zone->name);
+       if (r < 0)
+               goto ERROR;
+
+       // Open file
+       f = nw_daemon_config_fopen(zone->daemon, path, "w");
+       if (!f) {
+               r = -errno;
+               goto ERROR;
+       }
+
+       // Write the configuration
+       r = nw_config_write(zone->config, f);
        if (r)
-               return r;
+               goto ERROR;
 
-       return 0;
+ERROR:
+       if (f)
+               fclose(f);
+
+       return r;
 }
 
 const char* nw_zone_name(nw_zone* zone) {