]> git.ipfire.org Git - people/ms/network.git/blobdiff - src/networkd/link.c
networkd: Store operstate, too
[people/ms/network.git] / src / networkd / link.c
index 32a66cdf04873579b818eb0194399e39c372f099..6392a90a3b90c33024119df990d9245739e8f5b9 100644 (file)
 #                                                                             #
 #############################################################################*/
 
+#include <net/if.h>
 #include <stddef.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <systemd/sd-netlink.h>
 
 #include "link.h"
 #include "links.h"
 #include "logging.h"
+#include "string.h"
 
 struct nw_link {
-       struct nw_daemon* daemon;
+       nw_daemon* daemon;
        int nrefs;
 
        // Interface Index
        int ifindex;
+
+       // Interface Name
+       char ifname[IF_NAMESIZE];
+
+       // MTU
+       uint32_t mtu;
+       uint32_t min_mtu;
+       uint32_t max_mtu;
+
+       // Flags
+       unsigned int flags;
+       uint8_t operstate;
 };
 
-int nw_link_create(struct nw_link** link, struct nw_daemon* daemon, int ifindex) {
+int nw_link_create(nw_link** link, nw_daemon* daemon, int ifindex) {
        // Allocate a new object
-       struct nw_link* l = calloc(1, sizeof(*l));
+       nw_link* l = calloc(1, sizeof(*l));
        if (!l)
                return 1;
 
@@ -58,20 +73,20 @@ int nw_link_create(struct nw_link** link, struct nw_daemon* daemon, int ifindex)
        return 0;
 }
 
-static void nw_link_free(struct nw_link* link) {
+static void nw_link_free(nw_link* link) {
        DEBUG("Freeing link (ifindex = %d)\n", link->ifindex);
 
        if (link->daemon)
                nw_daemon_unref(link->daemon);
 }
 
-struct nw_link* nw_link_ref(struct nw_link* link) {
+nw_link* nw_link_ref(nw_link* link) {
        link->nrefs++;
 
        return link;
 }
 
-struct nw_link* nw_link_unref(struct nw_link* link) {
+nw_link* nw_link_unref(nw_link* link) {
        if (--link->nrefs > 0)
                return link;
 
@@ -79,19 +94,151 @@ struct nw_link* nw_link_unref(struct nw_link* link) {
        return NULL;
 }
 
-int nw_link_ifindex(struct nw_link* link) {
+int nw_link_ifindex(nw_link* link) {
        return link->ifindex;
 }
 
+static int nw_link_update_ifname(nw_link* link, sd_netlink_message* message) {
+       const char* ifname = NULL;
+       int r;
+
+       r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
+       if (r < 0) {
+               ERROR("Could not read link name for link %d: %m\n", link->ifindex);
+               return 1;
+       }
+
+       // Do nothing if the name is already set
+       if (strcmp(link->ifname, ifname) == 0)
+               return 0;
+
+       // Otherwise update the name
+       r = nw_string_set(link->ifname, ifname);
+       if (r) {
+               ERROR("Could not set link name: %m\n");
+               return 1;
+       }
+
+       DEBUG("Link %d has been renamed to '%s'\n", link->ifindex, link->ifname);
+
+       return 0;
+}
+
+static int nw_link_update_mtu(nw_link* link, sd_netlink_message* message) {
+       uint32_t mtu = 0;
+       uint32_t min_mtu = 0;
+       uint32_t max_mtu = 0;
+       int r;
+
+       // Read the MTU
+       r = sd_netlink_message_read_u32(message, IFLA_MTU, &mtu);
+       if (r < 0) {
+               ERROR("Could not read MTU for link %d: %m\n", link->ifindex);
+               return r;
+       }
+
+       // Read the minimum MTU
+       r = sd_netlink_message_read_u32(message, IFLA_MIN_MTU, &min_mtu);
+       if (r < 0) {
+               ERROR("Could not read the minimum MTU for link %d: %m\n", link->ifindex);
+               return r;
+       }
+
+       // Read the maximum MTU
+       r = sd_netlink_message_read_u32(message, IFLA_MAX_MTU, &max_mtu);
+       if (r < 0) {
+               ERROR("Could not read the maximum MTU for link %d: %m\n", link->ifindex);
+               return r;
+       }
+
+       // Set the maximum MTU to infinity
+       if (!max_mtu)
+               max_mtu = UINT32_MAX;
+
+       // Store min/max MTU
+       link->min_mtu = min_mtu;
+       link->max_mtu = max_mtu;
+
+       // End here, if the MTU has not been changed
+       if (link->mtu == mtu)
+               return 0;
+
+       DEBUG("Link %d: MTU has changed to %" PRIu32 " (min: %" PRIu32 ", max: %" PRIu32 ")\n",
+               link->ifindex, link->mtu, link->min_mtu, link->max_mtu);
+
+       // Store MTU
+       link->mtu = mtu;
+
+       return 0;
+}
+
+static int nw_link_update_flags(nw_link* link, sd_netlink_message* message) {
+       unsigned int flags = 0;
+       uint8_t operstate = 0;
+       int r;
+
+       // Fetch flags
+       r = sd_rtnl_message_link_get_flags(message, &flags);
+       if (r < 0) {
+               return DEBUG("Could not read link flags: %m\n");
+               return 1;
+       }
+
+       // Fetch operstate
+       r = sd_netlink_message_read_u8(message, IFLA_OPERSTATE, &operstate);
+       if (r < 1) {
+               ERROR("Could not read operstate: %m\n");
+               return 1;
+       }
+
+       // End here if there have been no changes
+       if (link->flags == flags && link->operstate == operstate)
+               return 0;
+
+       // XXX We should log any changes here
+
+       // Store the new flags & operstate
+       link->flags = flags;
+       link->operstate = operstate;
+
+
+       return 0;
+}
+
+/*
+       This function is called whenever anything changes, so that we can
+       update our internal link object.
+*/
+static int nw_link_update(nw_link* link, sd_netlink_message* message) {
+       int r;
+
+       // Update the interface name
+       r = nw_link_update_ifname(link, message);
+       if (r)
+               return r;
+
+       // Update the MTU
+       r = nw_link_update_mtu(link, message);
+       if (r)
+               return r;
+
+       // Update flags
+       r = nw_link_update_flags(link, message);
+       if (r)
+               return r;
+
+       return 0;
+}
+
 int nw_link_process(sd_netlink* rtnl, sd_netlink_message* message, void* data) {
-       struct nw_links* links = NULL;
-       struct nw_link* link = NULL;
+       nw_links* links = NULL;
+       nw_link* link = NULL;
        const char* ifname = NULL;
        int ifindex;
        uint16_t type;
        int r;
 
-       struct nw_daemon* daemon = (struct nw_daemon*)data;
+       nw_daemon* daemon = (nw_daemon*)data;
 
        // Fetch links
        links = nw_daemon_links(daemon);
@@ -166,7 +313,10 @@ int nw_link_process(sd_netlink* rtnl, sd_netlink_message* message, void* data) {
                                        goto ERROR;
                        }
 
-                       // TODO Import any data from the netlink message
+                       // Import any data from the netlink message
+                       r = nw_link_update(link, message);
+                       if (r)
+                               goto ERROR;
 
                        break;