]> git.ipfire.org Git - people/ms/network.git/blobdiff - src/networkd/ports.c
networkd: Implement smarter handling of the configuration file hierarchy
[people/ms/network.git] / src / networkd / ports.c
index 19a3a5979c0280324d92def503b63463be4bcae9..95a13e37a06ba1d467c59828566d587d178419aa 100644 (file)
@@ -18,6 +18,7 @@
 #                                                                             #
 #############################################################################*/
 
+#include <dirent.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/queue.h>
 #include "util.h"
 
 struct nw_ports_entry {
-       struct nw_port* port;
+       nw_port* port;
 
        // Link to the other entries
        STAILQ_ENTRY(nw_ports_entry) nodes;
 };
 
 struct nw_ports {
-       struct nw_daemon* daemon;
+       nw_daemon* daemon;
        int nrefs;
 
        // Port Entries
@@ -47,8 +48,8 @@ struct nw_ports {
        unsigned int num;
 };
 
-int nw_ports_create(struct nw_ports** ports, struct nw_daemon* daemon) {
-       struct nw_ports* p = calloc(1, sizeof(*p));
+int nw_ports_create(nw_ports** ports, nw_daemon* daemon) {
+       nw_ports* p = calloc(1, sizeof(*p));
        if (!p)
                return 1;
 
@@ -67,7 +68,7 @@ int nw_ports_create(struct nw_ports** ports, struct nw_daemon* daemon) {
        return 0;
 }
 
-static void nw_ports_free(struct nw_ports* ports) {
+static void nw_ports_free(nw_ports* ports) {
        struct nw_ports_entry* entry = NULL;
 
        while (!STAILQ_EMPTY(&ports->entries)) {
@@ -84,13 +85,13 @@ static void nw_ports_free(struct nw_ports* ports) {
        }
 }
 
-struct nw_ports* nw_ports_ref(struct nw_ports* ports) {
+nw_ports* nw_ports_ref(nw_ports* ports) {
        ports->nrefs++;
 
        return ports;
 }
 
-struct nw_ports* nw_ports_unref(struct nw_ports* ports) {
+nw_ports* nw_ports_unref(nw_ports* ports) {
        if (--ports->nrefs > 0)
                return ports;
 
@@ -98,7 +99,20 @@ struct nw_ports* nw_ports_unref(struct nw_ports* ports) {
        return NULL;
 }
 
-static int nw_ports_add_port(struct nw_ports* ports, struct nw_port* port) {
+int nw_ports_save(nw_ports* ports) {
+       struct nw_ports_entry* entry = NULL;
+       int r;
+
+       STAILQ_FOREACH(entry, &ports->entries, nodes) {
+               r = nw_port_save(entry->port);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
+static int nw_ports_add_port(nw_ports* ports, nw_port* port) {
        // Allocate a new entry
        struct nw_ports_entry* entry = calloc(1, sizeof(*entry));
        if (!entry)
@@ -116,30 +130,15 @@ static int nw_ports_add_port(struct nw_ports* ports, struct nw_port* port) {
        return 0;
 }
 
-static int __nw_ports_enumerate(const char* path, const struct stat* s, void* data) {
-       struct nw_port* port = NULL;
+static int __nw_ports_enumerate(struct dirent* entry, FILE* f, void* data) {
+       nw_port* port = NULL;
        int r;
 
-       struct nw_ports* ports = (struct 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;
+       nw_ports* ports = (nw_ports*)data;
 
        // Create a new port
-       r = nw_port_create(&port, name);
-       if (r)
+       r = nw_port_open(&port, ports->daemon, entry->d_name, f);
+       if (r < 0 || r == 1)
                goto ERROR;
 
        // Add the port to the list
@@ -154,6 +153,93 @@ ERROR:
        return r;
 }
 
-int nw_ports_enumerate(struct nw_ports* ports) {
-       return nw_ftw(PORT_CONFIG_DIR, PORT_CONFIG_DIR "/*", __nw_ports_enumerate, ports);
+int nw_ports_enumerate(nw_ports* ports) {
+       nw_configd* configd = NULL;
+       int r;
+
+       // Fetch ports configuration directory
+       configd = nw_daemon_configd(ports->daemon, "ports");
+       if (!configd)
+               return 0;
+
+       // Walk through all files
+       r = nw_configd_walk(configd, __nw_ports_enumerate, ports);
+
+       // Cleanup
+       nw_configd_unref(configd);
+
+       return r;
+}
+
+nw_port* nw_ports_get_by_name(nw_ports* ports, const char* name) {
+       struct nw_ports_entry* entry = NULL;
+
+       STAILQ_FOREACH(entry, &ports->entries, nodes) {
+               const char* __name = nw_port_name(entry->port);
+
+               // If the name matches, return a reference to the zone
+               if (strcmp(name, __name) == 0)
+                       return nw_port_ref(entry->port);
+       }
+
+       // No match found
+       return NULL;
+}
+
+int nw_ports_bus_paths(nw_ports* ports, char*** paths) {
+       struct nw_ports_entry* entry = NULL;
+       char* path = NULL;
+
+       // Allocate an array for all paths
+       char** p = calloc(ports->num + 1, sizeof(*p));
+       if (!p)
+               return 1;
+
+       unsigned int i = 0;
+
+       // Walk through all ports
+       STAILQ_FOREACH(entry, &ports->entries, nodes) {
+               // Generate the bus path
+               path = nw_port_bus_path(entry->port);
+               if (!path)
+                       goto ERROR;
+
+               // Append the bus path to the array
+               p[i++] = path;
+       }
+
+       // Return pointer
+       *paths = p;
+
+       return 0;
+
+ERROR:
+       if (p) {
+               for (char** e = p; *e; e++)
+                       free(*e);
+               free(p);
+       }
+
+       return 1;
+}
+
+int nw_ports_walk(nw_ports* ports, nw_ports_walk_callback callback, void* data) {
+       struct nw_ports_entry* entry = NULL;
+       int r;
+
+       STAILQ_FOREACH(entry, &ports->entries, nodes) {
+               r = callback(ports->daemon, entry->port, data);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
+static int __nw_ports_reconfigure(nw_daemon* daemon, nw_port* port, void* data) {
+       return nw_port_reconfigure(port);
+}
+
+int nw_ports_reconfigure(nw_ports* ports) {
+       return nw_ports_walk(ports, __nw_ports_reconfigure, NULL);
 }