From e331e24649213f2e093e16e4d3d64ee823dfc375 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Wed, 4 Feb 2015 11:44:37 +0100 Subject: [PATCH] networkd: add basic dbus API MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Only the very basics, more to come. For now: $ busctl tree org.freedesktop.network1 └─/org/freedesktop/network1 └─/org/freedesktop/network1/link ├─/org/freedesktop/network1/link/1 ├─/org/freedesktop/network1/link/2 ├─/org/freedesktop/network1/link/3 ├─/org/freedesktop/network1/link/4 ├─/org/freedesktop/network1/link/5 ├─/org/freedesktop/network1/link/6 ├─/org/freedesktop/network1/link/7 ├─/org/freedesktop/network1/link/8 └─/org/freedesktop/network1/link/9 $ busctl introspect org.freedesktop.network1 /org/freedesktop/network1 NAME TYPE SIGNATURE RESULT/VALUE FLAGS org.freedesktop.network1.Manager interface - - - .OperationalState property s "carrier" emits-change $ busctl introspect org.freedesktop.network1 /org/freedesktop/network1/link/1 NAME TYPE SIGNATURE RESULT/VALUE FLAGS org.freedesktop.network1.Link interface - - - .AdministrativeState property s "unmanaged" emits-change .OperationalState property s "carrier" emits-change --- Makefile.am | 11 ++ src/network/networkd-link-bus.c | 122 +++++++++++++++++++ src/network/networkd-link.c | 48 +++++--- src/network/networkd-link.h | 18 +-- src/network/networkd-manager-bus.c | 48 ++++++++ src/network/networkd-manager.c | 31 ++++- src/network/networkd.h | 20 +++ src/network/org.freedesktop.network1.conf | 42 +++++++ src/network/org.freedesktop.network1.service | 12 ++ units/org.freedesktop.network1.busname | 14 +++ 10 files changed, 334 insertions(+), 32 deletions(-) create mode 100644 src/network/networkd-link-bus.c create mode 100644 src/network/networkd-manager-bus.c create mode 100644 src/network/org.freedesktop.network1.conf create mode 100644 src/network/org.freedesktop.network1.service create mode 100644 units/org.freedesktop.network1.busname diff --git a/Makefile.am b/Makefile.am index 14f682755..53ad568d7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5585,6 +5585,7 @@ libsystemd_networkd_core_la_SOURCES = \ src/network/networkd-netdev-bond.c \ src/network/networkd-netdev-bridge.c \ src/network/networkd-link.c \ + src/network/networkd-link-bus.c \ src/network/networkd-ipv4ll.c \ src/network/networkd-dhcp4.c \ src/network/networkd-dhcp6.c \ @@ -5592,6 +5593,7 @@ libsystemd_networkd_core_la_SOURCES = \ src/network/networkd-address.c \ src/network/networkd-route.c \ src/network/networkd-manager.c \ + src/network/networkd-manager-bus.c \ src/network/networkd-fdb.c \ src/network/networkd-address-pool.c @@ -5673,6 +5675,15 @@ nodist_systemunit_DATA += \ units/systemd-networkd.service \ units/systemd-networkd-wait-online.service +dist_systemunit_DATA_busnames += \ + units/org.freedesktop.network1.busname + +dist_dbussystemservice_DATA += \ + src/network/org.freedesktop.network1.service + +dist_dbuspolicy_DATA += \ + src/network/org.freedesktop.network1.conf + GENERAL_ALIASES += \ $(systemunitdir)/systemd-networkd.socket $(pkgsysconfdir)/system/sockets.target.wants/systemd-networkd.socket \ $(systemunitdir)/systemd-networkd.service $(pkgsysconfdir)/system/multi-user.target.wants/systemd-networkd.service \ diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c new file mode 100644 index 000000000..645c47ae8 --- /dev/null +++ b/src/network/networkd-link-bus.c @@ -0,0 +1,122 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2015 Tom Gundersen + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "bus-util.h" +#include "strv.h" + +#include "networkd.h" +#include "networkd-link.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState); + +const sd_bus_vtable link_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_VTABLE_END +}; + +static char *link_bus_path(Link *link) { + char *p; + + assert(link); + assert(link->ifindex > 0); + + asprintf(&p, "/org/freedesktop/network1/link/%d", link->ifindex); + + return p; +} + +int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + Link *link; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(m); + assert(nodes); + + HASHMAP_FOREACH(link, m->links, i) { + char *p; + + p = link_bus_path(link); + if (!p) + return -ENOMEM; + + r = strv_consume(&l, p); + if (r < 0) + return r; + } + + *nodes = l; + l = NULL; + + return 1; +} + +int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Link *link; + int ifindex, r; + + assert(bus); + assert(path); + assert(interface); + assert(m); + assert(found); + + if (sscanf(path, "/org/freedesktop/network1/link/%d", &ifindex) != 1) + return 0; + + r = link_get(m, ifindex, &link); + if (r < 0) + return 0; + + *found = link; + + return 1; +} + +int link_send_changed(Link *link, const char *property, ...) { + _cleanup_free_ char *p = NULL; + char **l; + + assert(link); + assert(link->manager); + + l = strv_from_stdarg_alloca(property); + + p = link_bus_path(link); + if (!p) + return -ENOMEM; + + return sd_bus_emit_properties_changed_strv( + link->manager->bus, + p, + "org.freedesktop.network1.Link", + l); +} diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 077626cd1..f4ab97fb1 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -338,11 +338,24 @@ int link_get(Manager *m, int ifindex, Link **ret) { return 0; } +static void link_set_state(Link *link, LinkState state) { + assert(link); + + if (link->state == state) + return; + + link->state = state; + + link_send_changed(link, "AdministrativeState", NULL); + + return; +} + void link_drop(Link *link) { if (!link || link->state == LINK_STATE_LINGER) return; - link->state = LINK_STATE_LINGER; + link_set_state(link, LINK_STATE_LINGER); log_link_debug(link, "link removed"); @@ -356,7 +369,7 @@ static void link_enter_unmanaged(Link *link) { log_link_debug(link, "unmanaged"); - link->state = LINK_STATE_UNMANAGED; + link_set_state(link, LINK_STATE_UNMANAGED); link_save(link); } @@ -430,7 +443,7 @@ void link_enter_failed(Link *link) { log_link_warning(link, "failed"); - link->state = LINK_STATE_FAILED; + link_set_state(link, LINK_STATE_FAILED); link_stop_clients(link); @@ -473,7 +486,7 @@ static int link_enter_configured(Link *link) { log_link_info(link, "link configured"); - link->state = LINK_STATE_CONFIGURED; + link_set_state(link, LINK_STATE_CONFIGURED); link_save(link); @@ -536,7 +549,7 @@ static int link_enter_set_routes(Link *link) { assert(link->network); assert(link->state == LINK_STATE_SETTING_ADDRESSES); - link->state = LINK_STATE_SETTING_ROUTES; + link_set_state(link, LINK_STATE_SETTING_ROUTES); LIST_FOREACH(routes, rt, link->network->static_routes) { r = route_configure(rt, link, &route_handler); @@ -617,7 +630,7 @@ static int link_enter_set_addresses(Link *link) { assert(link->network); assert(link->state != _LINK_STATE_INVALID); - link->state = LINK_STATE_SETTING_ADDRESSES; + link_set_state(link, LINK_STATE_SETTING_ADDRESSES); LIST_FOREACH(addresses, ad, link->network->static_addresses) { r = address_configure(ad, link, &address_handler); @@ -1153,7 +1166,7 @@ static int link_enter_join_netdev(Link *link) { assert(link->network); assert(link->state == LINK_STATE_PENDING); - link->state = LINK_STATE_ENSLAVING; + link_set_state(link, LINK_STATE_ENSLAVING); link_save(link); @@ -1724,7 +1737,7 @@ int link_update(Link *link, sd_rtnl_message *m) { if (link->state == LINK_STATE_LINGER) { link_ref(link); log_link_info(link, "link readded"); - link->state = LINK_STATE_ENSLAVING; + link_set_state(link, LINK_STATE_ENSLAVING); } r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname); @@ -1843,11 +1856,11 @@ int link_update(Link *link, sd_rtnl_message *m) { } static void link_update_operstate(Link *link) { - + LinkOperationalState operstate; assert(link); if (link->kernel_operstate == IF_OPER_DORMANT) - link->operstate = LINK_OPERSTATE_DORMANT; + operstate = LINK_OPERSTATE_DORMANT; else if (link_has_carrier(link)) { Address *address; uint8_t scope = RT_SCOPE_NOWHERE; @@ -1863,17 +1876,22 @@ static void link_update_operstate(Link *link) { if (scope < RT_SCOPE_SITE) /* universally accessible addresses found */ - link->operstate = LINK_OPERSTATE_ROUTABLE; + operstate = LINK_OPERSTATE_ROUTABLE; else if (scope < RT_SCOPE_HOST) /* only link or site local addresses found */ - link->operstate = LINK_OPERSTATE_DEGRADED; + operstate = LINK_OPERSTATE_DEGRADED; else /* no useful addresses found */ - link->operstate = LINK_OPERSTATE_CARRIER; + operstate = LINK_OPERSTATE_CARRIER; } else if (link->flags & IFF_UP) - link->operstate = LINK_OPERSTATE_NO_CARRIER; + operstate = LINK_OPERSTATE_NO_CARRIER; else - link->operstate = LINK_OPERSTATE_OFF; + operstate = LINK_OPERSTATE_OFF; + + if (link->operstate != operstate) { + link->operstate = operstate; + link_send_changed(link, "OperationalState", NULL); + } } int link_save(Link *link) { diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 81e97fa95..b23712011 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -36,17 +36,6 @@ typedef enum LinkState { _LINK_STATE_INVALID = -1 } LinkState; -typedef enum LinkOperationalState { - LINK_OPERSTATE_OFF, - LINK_OPERSTATE_NO_CARRIER, - LINK_OPERSTATE_DORMANT, - LINK_OPERSTATE_CARRIER, - LINK_OPERSTATE_DEGRADED, - LINK_OPERSTATE_ROUTABLE, - _LINK_OPERSTATE_MAX, - _LINK_OPERSTATE_INVALID = -1 -} LinkOperationalState; - struct Link { Manager *manager; @@ -128,8 +117,11 @@ int icmp6_configure(Link *link); const char* link_state_to_string(LinkState s) _const_; LinkState link_state_from_string(const char *s) _pure_; -const char* link_operstate_to_string(LinkOperationalState s) _const_; -LinkOperationalState link_operstate_from_string(const char *s) _pure_; +extern const sd_bus_vtable link_vtable[]; + +int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +int link_send_changed(Link *link, const char *property, ...) _sentinel_; DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); #define _cleanup_link_unref_ _cleanup_(link_unrefp) diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c new file mode 100644 index 000000000..7753c5dbc --- /dev/null +++ b/src/network/networkd-manager-bus.c @@ -0,0 +1,48 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2015 Tom Gundersen + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "bus-util.h" + +#include "networkd.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); + +const sd_bus_vtable manager_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Manager, operational_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_VTABLE_END +}; + +int manager_send_changed(Manager *manager, const char *property, ...) { + char **l; + + assert(manager); + + l = strv_from_stdarg_alloca(property); + + return sd_bus_emit_properties_changed_strv( + manager->bus, + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + l); +} diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 4d27272b3..40328a36c 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -151,10 +151,6 @@ int manager_connect_bus(Manager *m) { } if (r < 0) return r; - r = sd_bus_attach_event(m->bus, m->event, 0); - if (r < 0) - return r; - r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot, "type='signal'," "sender='org.freedesktop.login1'," @@ -166,6 +162,26 @@ int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to add match for PrepareForSleep: %m"); + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to add manager object vtable: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add link object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add link enumerator: %m"); + + r = sd_bus_request_name(m->bus, "org.freedesktop.network1", 0); + if (r < 0) + return log_error_errno(r, "Failed to register name: %m"); + + r = sd_bus_attach_event(m->bus, m->event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + return 0; } @@ -741,6 +757,13 @@ int manager_save(Manager *m) { goto fail; } + if (m->operational_state != operstate) { + m->operational_state = operstate; + r = manager_send_changed(m, "OperationalState", NULL); + if (r < 0) + log_error_errno(r, "Could not emit changed OperationalState: %m"); + } + return 0; fail: diff --git a/src/network/networkd.h b/src/network/networkd.h index e053bd624..9f3a5ea9d 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -72,6 +72,17 @@ typedef enum LLMNRSupport { _LLMNR_SUPPORT_INVALID = -1, } LLMNRSupport; +typedef enum LinkOperationalState { + LINK_OPERSTATE_OFF, + LINK_OPERSTATE_NO_CARRIER, + LINK_OPERSTATE_DORMANT, + LINK_OPERSTATE_CARRIER, + LINK_OPERSTATE_DEGRADED, + LINK_OPERSTATE_ROUTABLE, + _LINK_OPERSTATE_MAX, + _LINK_OPERSTATE_INVALID = -1 +} LinkOperationalState; + struct FdbEntry { Network *network; unsigned section; @@ -209,6 +220,7 @@ struct Manager { bool enumerating; char *state_file; + LinkOperationalState operational_state; Hashmap *links; Hashmap *netdevs; @@ -222,6 +234,8 @@ extern const char* const network_dirs[]; /* Manager */ +extern const sd_bus_vtable manager_vtable[]; + int manager_new(Manager **ret); void manager_free(Manager *m); @@ -231,6 +245,7 @@ bool manager_should_reload(Manager *m); int manager_rtnl_enumerate_links(Manager *m); int manager_rtnl_enumerate_addresses(Manager *m); +int manager_send_changed(Manager *m, const char *property, ...) _sentinel_; int manager_save(Manager *m); int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); @@ -394,3 +409,8 @@ const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_; AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_; int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); + +/* Opeartional State */ + +const char* link_operstate_to_string(LinkOperationalState s) _const_; +LinkOperationalState link_operstate_from_string(const char *s) _pure_; diff --git a/src/network/org.freedesktop.network1.conf b/src/network/org.freedesktop.network1.conf new file mode 100644 index 000000000..52dad3366 --- /dev/null +++ b/src/network/org.freedesktop.network1.conf @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/network/org.freedesktop.network1.service b/src/network/org.freedesktop.network1.service new file mode 100644 index 000000000..bea885fe5 --- /dev/null +++ b/src/network/org.freedesktop.network1.service @@ -0,0 +1,12 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.network1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.network1.service diff --git a/units/org.freedesktop.network1.busname b/units/org.freedesktop.network1.busname new file mode 100644 index 000000000..c68f4ade3 --- /dev/null +++ b/units/org.freedesktop.network1.busname @@ -0,0 +1,14 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Network Service Bus Name +Documentation=man:systemd-networkd.service(8) + +[BusName] +Service=systemd-networkd.service +AllowWorld=talk -- 2.30.2