]> git.ipfire.org Git - people/ms/network.git/blobdiff - src/networkd/port.c
networkd: ports: Keep a permanent reference to links
[people/ms/network.git] / src / networkd / port.c
index f78489b02d29ce3a950ef15dba802bbead9d6ca1..3c4f0b3eef9c7009b1f9e2c972cdf2a5d31ea33d 100644 (file)
 
 #include <limits.h>
 #include <net/if.h>
+#include <stdint.h>
 #include <stdlib.h>
 
+#include <systemd/sd-bus.h>
+
+#include "address.h"
 #include "config.h"
+#include "link.h"
 #include "logging.h"
 #include "string.h"
 #include "port.h"
 
 struct nw_port {
+       nw_daemon* daemon;
        int nrefs;
 
+       // Link
+       nw_link* link;
+
        char name[IF_NAMESIZE];
        nw_port_type_t type;
 
        // Configuration
-       struct nw_config *config;
+       nw_config *config;
+
+       // Common attributes
+       nw_address_t address;
 };
 
 static const struct nw_port_type_map {
@@ -56,18 +68,66 @@ static nw_port_type_t nw_port_type_from_string(const char* s) {
        return NW_PORT_UNKNOWN;
 }
 
-static void nw_port_free(struct nw_port* port) {
+static void nw_port_free(nw_port* port) {
+       if (port->link)
+               nw_link_unref(port->link);
        if (port->config)
                nw_config_unref(port->config);
+       if (port->daemon)
+               nw_daemon_unref(port->daemon);
 
        free(port);
 }
 
-static int nw_port_setup_common(struct nw_port* port) {
-       return 0; // XXX TODO
+static int nw_port_setup_address(nw_port* port) {
+       int r;
+
+       // Read ADDRESS from configuration
+       const char* s = nw_config_get(port->config, "ADDRESS");
+       if (!s) {
+               ERROR("Port %s: Address isn't set\n", port->name);
+               goto ERROR;
+       }
+
+       // Parse the address
+       r = nw_address_from_string(&port->address, s);
+       if (r) {
+               ERROR("Port %s: Could not parse address: %m\n", port->name);
+               goto ERROR;
+       }
+
+       // Check if this address is usable
+       r = nw_address_is_multicast(&port->address);
+       if (r) {
+               DEBUG("Port %s: Multicast bit is set on Ethernet address\n", port->name);
+               goto ERROR;
+       }
+
+       return 0;
+
+ERROR:
+       // Generate a random Ethernet address
+       r = nw_address_generate(&port->address);
+       if (r) {
+               ERROR("Could not generate a random Ethernet address: %m\n");
+               return r;
+       }
+
+       return 0;
+}
+
+static int nw_port_setup_common(nw_port* port) {
+       int r;
+
+       // Address
+       r = nw_port_setup_address(port);
+       if (r)
+               return r;
+
+       return 0;
 }
 
-static nw_port_type_t nw_port_setup_type(struct nw_port* port) {
+static nw_port_type_t nw_port_setup_type(nw_port* port) {
        const char* type = nw_config_get(port->config, "TYPE");
        if (!type)
                return NW_PORT_UNKNOWN;
@@ -75,10 +135,18 @@ static nw_port_type_t nw_port_setup_type(struct nw_port* port) {
        return nw_port_type_from_string(type);
 }
 
-static int nw_port_setup(struct nw_port* port) {
+static int nw_port_setup(nw_port* port) {
        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);
+       }
+
        // Compose the path to the main configuration file
        r = nw_path_join(path, PORT_CONFIG_DIR, port->name);
        if (r)
@@ -112,14 +180,17 @@ static int nw_port_setup(struct nw_port* port) {
        return 0;
 }
 
-int nw_port_create(struct nw_port** port, const char* name) {
+int nw_port_create(nw_port** port, nw_daemon* daemon, const char* name) {
        int r;
 
        // Allocate a new object
-       struct nw_port* p = calloc(1, sizeof(*p));
+       nw_port* p = calloc(1, sizeof(*p));
        if (!p)
                return 1;
 
+       // Store a reference to the daemon
+       p->daemon = nw_daemon_ref(daemon);
+
        // Initialize reference counter
        p->nrefs = 1;
 
@@ -141,13 +212,13 @@ ERROR:
        return r;
 }
 
-struct nw_port* nw_port_ref(struct nw_port* port) {
+nw_port* nw_port_ref(nw_port* port) {
        port->nrefs++;
 
        return port;
 }
 
-struct nw_port* nw_port_unref(struct nw_port* port) {
+nw_port* nw_port_unref(nw_port* port) {
        if (--port->nrefs > 0)
                return port;
 
@@ -155,6 +226,46 @@ struct nw_port* nw_port_unref(struct nw_port* port) {
        return NULL;
 }
 
-const char* nw_port_name(struct nw_port* port) {
+int nw_port_save(nw_port* port) {
+       int r;
+
+       r = nw_config_write(port->config);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+const char* nw_port_name(nw_port* port) {
        return port->name;
 }
+
+char* nw_port_bus_path(nw_port* port) {
+       char* p = NULL;
+       int r;
+
+       // Encode the bus path
+       r = sd_bus_path_encode("/org/ipfire/network1/port", port->name, &p);
+       if (r < 0)
+               return NULL;
+
+       return p;
+}
+
+static nw_link* nw_port_get_link(nw_port* port) {
+       if (!port->link)
+               return NULL;
+
+       return nw_link_ref(port->link);
+}
+
+const nw_address_t* nw_port_get_address(nw_port* port) {
+       return &port->address;
+}
+
+int nw_port_has_carrier(nw_port* port) {
+       if (!port->link)
+               return 0;
+
+       return nw_link_has_carrier(port->link);
+}