return 1;
}
+ // Register callback for deleted interfaces
+ r = sd_netlink_add_match(daemon->rtnl, NULL, RTM_DELLINK, nw_link_process, NULL,
+ daemon, "networkd-RTM_DELLINK");
+ if (r < 0) {
+ ERROR("Could not register RTM_DELLINK: %m\n");
+ return 1;
+ }
+
return 0;
}
return daemon->rtnl;
}
+/*
+ Links
+*/
+struct nw_links* nw_daemon_links(struct nw_daemon* daemon) {
+ return nw_links_ref(daemon->links);
+}
+
+void nw_daemon_drop_link(struct nw_daemon* daemon, struct nw_link* link) {
+ if (!daemon->links)
+ return;
+
+ nw_links_drop_link(daemon->links, link);
+}
+
+struct nw_link* nw_daemon_get_link_by_ifindex(struct nw_daemon* daemon, int ifindex) {
+ if (!daemon->links)
+ return NULL;
+
+ return nw_links_get_by_ifindex(daemon->links, ifindex);
+}
+
/*
Zones
*/
#include <systemd/sd-netlink.h>
-#include "zone.h"
-
struct nw_daemon;
+#include "link.h"
+#include "zone.h"
+
int nw_daemon_create(struct nw_daemon** daemon);
struct nw_daemon* nw_daemon_ref(struct nw_daemon* daemon);
*/
sd_netlink* nw_daemon_get_rtnl(struct nw_daemon* daemon);
+/*
+ Links
+*/
+struct nw_links* nw_daemon_links(struct nw_daemon* daemon);
+void nw_daemon_drop_link(struct nw_daemon* daemon, struct nw_link* link);
+struct nw_link* nw_daemon_get_link_by_ifindex(struct nw_daemon* daemon, int ifindex);
+
/*
Zones
*/
#include <stddef.h>
#include <stdlib.h>
+#include <systemd/sd-netlink.h>
+
#include "daemon.h"
#include "link.h"
+#include "links.h"
#include "logging.h"
struct nw_link {
// Store the ifindex
l->ifindex = ifindex;
+ DEBUG("New link allocated (ifindex = %d)\n", l->ifindex);
+
*link = l;
return 0;
}
static void nw_link_free(struct nw_link* link) {
+ DEBUG("Freeing link (ifindex = %d)\n", link->ifindex);
+
if (link->daemon)
nw_daemon_unref(link->daemon);
}
return NULL;
}
-int nw_link_process(sd_netlink* rtnl, sd_netlink_message* message, void* data) {
- DEBUG("nw_link_process called\n");
+int nw_link_ifindex(struct nw_link* link) {
+ return link->ifindex;
+}
- 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;
+ const char* ifname = NULL;
+ int ifindex;
+ uint16_t type;
+ int r;
+
+ struct nw_daemon* daemon = (struct nw_daemon*)data;
+
+ // Fetch links
+ links = nw_daemon_links(daemon);
+ if (!links) {
+ r = 1;
+ goto ERROR;
+ }
+
+ // Check if this message could be received
+ if (sd_netlink_message_is_error(message)) {
+ r = sd_netlink_message_get_errno(message);
+ if (r < 0)
+ ERROR("Could not receive link message: %m\n");
+
+ goto IGNORE;
+ }
+
+ // Fetch the message type
+ r = sd_netlink_message_get_type(message, &type);
+ if (r < 0) {
+ ERROR("Could not fetch message type: %m\n");
+ goto IGNORE;
+ }
+
+ // Check type
+ switch (type) {
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ break;
+
+ default:
+ ERROR("Received an unexpected message (type %u)\n", type);
+ goto IGNORE;
+ }
+
+ // Fetch the interface index
+ r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
+ if (r < 0) {
+ ERROR("Could not fetch ifindex: %m\n");
+ goto IGNORE;
+ }
+
+ // Check interface index
+ if (ifindex <= 0) {
+ ERROR("Received an invalid ifindex\n");
+ goto IGNORE;
+ }
+
+ // Fetch the interface name
+ r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
+ if (r < 0) {
+ ERROR("Received a netlink message without interface name: %m\n");
+ goto IGNORE;
+ }
+
+ // Try finding an existing link
+ link = nw_daemon_get_link_by_ifindex(daemon, ifindex);
+
+ switch (type) {
+ case RTM_NEWLINK:
+ // If the link doesn't exist, create it
+ if (!link) {
+ r = nw_link_create(&link, daemon, ifindex);
+ if (r) {
+ ERROR("Could not create link: %m\n");
+ goto ERROR;
+ }
+ }
+
+ // TODO Import any data from the netlink message
+
+ // Add it to the list
+ r = nw_links_add_link(links, link);
+ if (r)
+ goto ERROR;
+
+ break;
+
+ case RTM_DELLINK:
+ if (link)
+ nw_links_drop_link(links, link);
+
+ break;
+ }
+
+IGNORE:
+ r = 0;
+
+ERROR:
+ if (links)
+ nw_links_unref(links);
+ if (link)
+ nw_link_unref(link);
+
+ return r;
}
struct nw_link* nw_link_ref(struct nw_link* link);
struct nw_link* nw_link_unref(struct nw_link* link);
+int nw_link_ifindex(struct nw_link* link);
+
int nw_link_process(sd_netlink* rtnl, sd_netlink_message* message, void* data);
#endif /* NETWORKD_LINK_H */
#include <sys/queue.h>
#include "daemon.h"
+#include "logging.h"
#include "link.h"
#include "links.h"
return NULL;
}
+static struct nw_links_entry* nw_links_find_link(struct nw_links* links, const int ifindex) {
+ struct nw_links_entry* entry = NULL;
+
+ STAILQ_FOREACH(entry, &links->entries, nodes) {
+ if (nw_link_ifindex(entry->link) == ifindex)
+ return entry;
+ }
+
+ // No match found
+ return NULL;
+}
+
+int nw_links_add_link(struct nw_links* links, struct nw_link* link) {
+ // Allocate a new entry
+ struct nw_links_entry* entry = calloc(1, sizeof(*entry));
+ if (!entry)
+ return 1;
+
+ // Reference the link
+ entry->link = nw_link_ref(link);
+
+ // Add it to the list
+ STAILQ_INSERT_TAIL(&links->entries, entry, nodes);
+
+ // Increment the counter
+ links->num++;
+
+ return 0;
+}
+
+void nw_links_drop_link(struct nw_links* links, struct nw_link* link) {
+ struct nw_links_entry* entry = NULL;
+
+ entry = nw_links_find_link(links, nw_link_ifindex(link));
+ if (!entry)
+ return;
+
+ DEBUG("Dropping link %d\n", nw_link_ifindex(entry->link));
+
+ STAILQ_REMOVE(&links->entries, entry, nw_links_entry, nodes);
+ links->num--;
+}
+
int nw_links_enumerate(struct nw_links* links) {
sd_netlink_message* req = NULL;
sd_netlink_message* res = NULL;
return r;
}
+
+struct nw_link* nw_links_get_by_ifindex(struct nw_links* links, int ifindex) {
+ struct nw_links_entry* entry = NULL;
+
+ entry = nw_links_find_link(links, ifindex);
+ if (!entry)
+ return NULL;
+
+ return nw_link_ref(entry->link);
+}
#define NETWORKD_LINKS_H
#include "daemon.h"
+#include "link.h"
struct nw_links;
struct nw_links* nw_links_ref(struct nw_links* links);
struct nw_links* nw_links_unref(struct nw_links* links);
+int nw_links_add_link(struct nw_links* links, struct nw_link* link);
+void nw_links_drop_link(struct nw_links* links, struct nw_link* link);
+
int nw_links_enumerate(struct nw_links* links);
+struct nw_link* nw_links_get_by_ifindex(struct nw_links* links, int ifindex);
+
#endif /* NETWORKD_LINKS_H */