]> git.ipfire.org Git - network.git/commitdiff
networkd: Automatically reference/dereference links to zones/ports
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 14 Apr 2023 14:15:01 +0000 (14:15 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 14 Apr 2023 14:15:01 +0000 (14:15 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/networkd/daemon.c
src/networkd/daemon.h
src/networkd/link.c
src/networkd/links.c
src/networkd/port.c
src/networkd/port.h
src/networkd/zone.c
src/networkd/zone.h

index c6dad91ee7156fa58d2d09aa92cec9090b22645c..02ca8e2eb104886211409d0954b6999679bb49cd 100644 (file)
@@ -540,6 +540,13 @@ nw_ports* nw_daemon_ports(nw_daemon* daemon) {
        return nw_ports_ref(daemon->ports);
 }
 
+int nw_daemon_ports_walk(nw_daemon* daemon, nw_ports_walk_callback callback, void* data) {
+       if (!daemon->ports)
+               return 0;
+
+       return nw_ports_walk(daemon->ports, callback, data);
+}
+
 nw_port* nw_daemon_get_port_by_name(nw_daemon* daemon, const char* name) {
        if (!daemon->ports)
                return NULL;
index ce9a66023d1e0c802855bee28cbe8d1f9f40a72c..a14d33b229e50c32da254627371aff10f0bea5ae 100644 (file)
@@ -60,6 +60,7 @@ nw_link* nw_daemon_get_link_by_name(nw_daemon* daemon, const char* name);
        Ports
 */
 nw_ports* nw_daemon_ports(nw_daemon* daemon);
+int nw_daemon_ports_walk(nw_daemon* daemon, nw_ports_walk_callback callback, void* data);
 nw_port* nw_daemon_get_port_by_name(nw_daemon* daemon, const char* name);
 
 /*
index 949d0d8d228d33f962445cb25497533509f25f9e..09b9a62225d708180ca7baa8f830f4cd57920d4b 100644 (file)
@@ -114,6 +114,10 @@ int nw_link_ifindex(nw_link* link) {
 }
 
 const char* nw_link_ifname(nw_link* link) {
+       // Return NULL if name isn't set
+       if (!*link->ifname)
+               return NULL;
+
        return link->ifname;
 }
 
@@ -154,6 +158,12 @@ static int nw_link_update_ifname(nw_link* link, sd_netlink_message* message) {
 
        DEBUG("Link %d has been renamed to '%s'\n", link->ifindex, link->ifname);
 
+       // Assign link to ports
+       nw_daemon_ports_walk(link->daemon, __nw_port_set_link, link);
+
+       // Assign link to zones
+       nw_daemon_zones_walk(link->daemon, __nw_zone_set_link, link);
+
        return 0;
 }
 
index 3dd06d0f634838bf3bd99183899090f9b9d8c94a..40926f3e302e818f27663e03b7f5e255f44e1444 100644 (file)
@@ -141,6 +141,12 @@ void nw_links_drop_link(nw_links* links, struct nw_link* link) {
 
        STAILQ_REMOVE(&links->entries, entry, nw_links_entry, nodes);
        links->num--;
+
+       // Drop link from all ports
+       nw_daemon_ports_walk(links->daemon, __nw_port_drop_link, link);
+
+       // Drop link from all zones
+       nw_daemon_zones_walk(links->daemon, __nw_zone_drop_link, link);
 }
 
 int nw_links_enumerate(nw_links* links) {
index 7d023050d2053611f6bda46019b1490f1253ed35..37ab3a7c1b1aa58e23512267d3b79a0beadb858e 100644 (file)
@@ -135,39 +135,65 @@ static nw_port_type_t nw_port_setup_type(nw_port* port) {
        return nw_port_type_from_string(type);
 }
 
+static int nw_port_set_link(nw_port* port, nw_link* link) {
+       // Do nothing if the same link is being re-assigned
+       if (port->link == link)
+               return 0;
+
+       // Dereference the former link if set
+       if (port->link)
+               nw_link_unref(port->link);
+
+       // Store the new link
+       if (link) {
+               port->link = nw_link_ref(link);
+
+               DEBUG("Port %s: Assigned link %d\n", port->name, nw_link_ifindex(port->link));
+
+       // Or clear the pointer if no link has been provided
+       } else {
+               port->link = NULL;
+
+               DEBUG("Port %s: Removed link\n", port->name);
+       }
+
+       return 0;
+}
+
 static int nw_port_setup(nw_port* port) {
+       nw_link* link = NULL;
        char path[PATH_MAX];
        int r;
 
        // Find the link
-       port->link = nw_daemon_get_link_by_name(port->daemon, port->name);
-       if (port->link) {
-               DEBUG("%s: Found matching link %d\n", port->name, nw_link_ifindex(port->link));
-       } else {
-               DEBUG("%s: Could not find matching link\n", port->name);
+       link = nw_daemon_get_link_by_name(port->daemon, port->name);
+       if (link) {
+               r = nw_port_set_link(port, link);
+               if (r)
+                       goto ERROR;
        }
 
        // Compose the path to the main configuration file
        r = nw_path_join(path, PORT_CONFIG_DIR, port->name);
        if (r)
-               return r;
+               goto ERROR;
 
        // Initialize the configuration
        r = nw_config_create(&port->config, path);
        if (r)
-               return r;
+               goto ERROR;
 
        // Determine type
        port->type = nw_port_setup_type(port);
        if (!port->type) {
                ERROR("Could not determine type of port %s\n", port->name);
-               return 0;
+               goto ERROR;
        }
 
        // Perform some common initialization
        r = nw_port_setup_common(port);
        if (r)
-               return r;
+               goto ERROR;
 
        // Call any custom initialization
        switch (port->type) {
@@ -177,7 +203,11 @@ static int nw_port_setup(nw_port* port) {
                        break;
        }
 
-       return 0;
+ERROR:
+       if (link)
+               nw_link_unref(link);
+
+       return r;
 }
 
 int nw_port_create(nw_port** port, nw_daemon* daemon, const char* name) {
@@ -252,11 +282,35 @@ char* nw_port_bus_path(nw_port* port) {
        return p;
 }
 
-static nw_link* nw_port_get_link(nw_port* port) {
-       if (!port->link)
-               return NULL;
+int __nw_port_set_link(nw_daemon* daemon, nw_port* port, void* data) {
+       nw_link* link = (nw_link*)data;
+
+       // Fetch the link name
+       const char* ifname = nw_link_ifname(link);
+       if (!ifname) {
+               ERROR("Link does not have a name set\n");
+               return 1;
+       }
+
+       // Set link if the name matches
+       if (strcmp(port->name, ifname) == 0)
+               return nw_port_set_link(port, link);
+
+       // If we have the link set but the name did not match, we will remove it
+       else if (port->link == link)
+               return nw_port_set_link(port, NULL);
+
+       return 0;
+}
+
+int __nw_port_drop_link(nw_daemon* daemon, nw_port* port, void* data) {
+       nw_link* link = (nw_link*)data;
 
-       return nw_link_ref(port->link);
+       // Drop the link if it matches
+       if (port->link == link)
+               return nw_port_set_link(port, NULL);
+
+       return 0;
 }
 
 const nw_address_t* nw_port_get_address(nw_port* port) {
index 17c8c3cd20508d48a2a992c1de536b8722122900..3981c82addd47b641ea1e42e710ceecb1e8062d0 100644 (file)
@@ -44,6 +44,9 @@ const char* nw_port_name(nw_port* port);
 
 char* nw_port_bus_path(nw_port* port);
 
+int __nw_port_set_link(nw_daemon* daemon, nw_port* port, void* data);
+int __nw_port_drop_link(nw_daemon* daemon, nw_port* port, void* data);
+
 const nw_address_t* nw_port_get_address(nw_port* port);
 
 int nw_port_reconfigure(nw_port* port);
index 9daa0d3d19b49e51ee6a7f551a2cd95ceba7a3f7..00ab017f7901617010919b2608f9c48a4d0b4c32 100644 (file)
@@ -80,29 +80,59 @@ static void nw_zone_free(nw_zone* zone) {
        free(zone);
 }
 
+static int nw_zone_set_link(nw_zone* zone, nw_link* link) {
+       // Do nothing if the same link is being re-assigned
+       if (zone->link == link)
+               return 0;
+
+       // Dereference the former link if set
+       if (zone->link)
+               nw_link_unref(zone->link);
+
+       // Store the new link
+       if (link) {
+               zone->link = nw_link_ref(link);
+
+               DEBUG("Zone %s: Assigned link %d\n", zone->name, nw_link_ifindex(zone->link));
+
+       // Or clear the pointer if no link has been provided
+       } else {
+               zone->link = NULL;
+
+               DEBUG("Zone %s: Removed link\n", zone->name);
+       }
+
+       return 0;
+}
+
 static int nw_zone_setup(nw_zone* zone) {
+       nw_link* link = NULL;
        char path[PATH_MAX];
        int r;
 
        // Find the link
-       zone->link = nw_daemon_get_link_by_name(zone->daemon, zone->name);
-       if (zone->link) {
-               DEBUG("%s: Found matching link %d\n", zone->name, nw_link_ifindex(zone->link));
-       } else {
-               DEBUG("%s: Could not find matching link\n", zone->name);
+       link = nw_daemon_get_link_by_name(zone->daemon, zone->name);
+       if (link) {
+               r = nw_zone_set_link(zone, link);
+               if (r)
+                       goto ERROR;
        }
 
        // Compose the path to the main configuration file
        r = nw_zone_path(zone, path, "%s", "settings");
        if (r)
-               return r;
+               goto ERROR;
 
        // Initialize the configuration
        r = nw_config_create(&zone->config, path);
        if (r)
-               return r;
+               goto ERROR;
 
-       return 0;
+ERROR:
+       if (link)
+               nw_link_unref(link);
+
+       return r;
 }
 
 int nw_zone_create(nw_zone** zone, nw_daemon* daemon, const char* name) {
@@ -177,11 +207,35 @@ char* nw_zone_bus_path(nw_zone* zone) {
        return p;
 }
 
-static nw_link* nw_zone_get_link(nw_zone* zone) {
-       if (!zone->link)
-               return NULL;
+int __nw_zone_set_link(nw_daemon* daemon, nw_zone* zone, void* data) {
+       nw_link* link = (nw_link*)data;
+
+       // Fetch the link name
+       const char* ifname = nw_link_ifname(link);
+       if (!ifname) {
+               ERROR("Link does not have a name set\n");
+               return 1;
+       }
+
+       // Set link if the name matches
+       if (strcmp(zone->name, ifname) == 0)
+               return nw_zone_set_link(zone, link);
+
+       // If we have the link set but the name did not match, we will remove it
+       else if (zone->link == link)
+               return nw_zone_set_link(zone, NULL);
 
-       return nw_link_ref(zone->link);
+       return 0;
+}
+
+int __nw_zone_drop_link(nw_daemon* daemon, nw_zone* zone, void* data) {
+       nw_link* link = (nw_link*)data;
+
+       // Drop the link if it matches
+       if (zone->link == link)
+               return nw_zone_set_link(zone, NULL);
+
+       return 0;
 }
 
 int nw_zone_reconfigure(nw_zone* zone) {
index 591e467d6f03fcc12707a089b77adf31fbfdbff9..ad348d7111378928042b5912176f3ecb39674c9a 100644 (file)
@@ -41,6 +41,9 @@ const char* nw_zone_name(nw_zone* zone);
 
 char* nw_zone_bus_path(nw_zone* zone);
 
+int __nw_zone_set_link(nw_daemon* daemon, nw_zone* zone, void* data);
+int __nw_zone_drop_link(nw_daemon* daemon, nw_zone* zone, void* data);
+
 int nw_zone_reconfigure(nw_zone* zone);
 
 int nw_zone_has_carrier(nw_zone* zone);