[systemd-commits] 5 commits - Makefile.am src/libsystemd src/network src/systemd
Tom Gundersen
tomegun at kemper.freedesktop.org
Sun Feb 8 11:24:47 PST 2015
Makefile.am | 7 +
src/libsystemd/sd-rtnl/rtnl-message.c | 124 ++++++++++++++++++++++++++++----
src/libsystemd/sd-rtnl/rtnl-types.c | 69 ++++++++++++++++--
src/libsystemd/sd-rtnl/rtnl-types.h | 7 +
src/libsystemd/sd-rtnl/test-rtnl.c | 22 +++++
src/network/networkd-manager.c | 10 ++
src/network/networkd-network-bus.c | 128 ++++++++++++++++++++++++++++++++++
src/network/networkd-network.c | 48 ++++++++++++
src/network/networkd.h | 10 ++
src/systemd/sd-rtnl.h | 2
10 files changed, 399 insertions(+), 28 deletions(-)
New commits:
commit 3175fcdec5d748e8db85a3e7fe1cb67f5f6a865d
Author: Tom Gundersen <teg at jklm.no>
Date: Sun Feb 8 13:27:56 2015 +0100
networkd: add basic org.freedesktop.network1.Network interface
diff --git a/Makefile.am b/Makefile.am
index 3dc5fa0..1ab2e79 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5589,6 +5589,7 @@ libsystemd_networkd_core_la_SOURCES = \
src/network/networkd-dhcp4.c \
src/network/networkd-dhcp6.c \
src/network/networkd-network.c \
+ src/network/networkd-network-bus.c \
src/network/networkd-address.c \
src/network/networkd-route.c \
src/network/networkd-manager.c \
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index e2c8a23..4617f11 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -174,6 +174,14 @@ int manager_connect_bus(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to add link enumerator: %m");
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add network object vtable: %m");
+
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add network 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");
diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c
new file mode 100644
index 0000000..a167857
--- /dev/null
+++ b/src/network/networkd-network-bus.c
@@ -0,0 +1,128 @@
+/*-*- 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include "bus-util.h"
+#include "bus-label.h"
+#include "strv.h"
+
+#include "networkd.h"
+
+const sd_bus_vtable network_vtable[] = {
+ SD_BUS_VTABLE_START(0),
+
+ SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST),
+/* SD_BUS_PROPERTY("MatchMAC", "s", NULL TODO, offsetof(Network, match_mac), SD_BUS_VTABLE_PROPERTY_CONST), */
+ SD_BUS_PROPERTY("MatchPath", "s", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("MatchDriver", "s", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("MatchType", "s", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("MatchName", "s", NULL, offsetof(Network, match_name), SD_BUS_VTABLE_PROPERTY_CONST),
+
+ SD_BUS_VTABLE_END
+};
+
+static char *network_bus_path(Network *network) {
+ _cleanup_free_ char *e = NULL;
+ _cleanup_free_ char *name = NULL;
+ char *networkname;
+ char *d;
+
+ assert(network);
+ assert(network->filename);
+
+ name = strdup(network->filename);
+ if (!name)
+ return NULL;
+
+ networkname = basename(name);
+
+ d = strrchr(networkname, '.');
+ if (!d)
+ return NULL;
+
+ assert(streq(d, ".network"));
+
+ *d = '\0';
+
+ e = bus_label_escape(networkname);
+ if (!e)
+ return NULL;
+
+ return strappend("/org/freedesktop/network1/network/", e);
+}
+
+int network_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;
+ Network *network;
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(m);
+ assert(nodes);
+
+ LIST_FOREACH(networks, network, m->networks) {
+ char *p;
+
+ p = network_bus_path(network);
+ if (!p)
+ return -ENOMEM;
+
+ r = strv_consume(&l, p);
+ if (r < 0)
+ return r;
+ }
+
+ *nodes = l;
+ l = NULL;
+
+ return 1;
+}
+
+int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
+ Manager *m = userdata;
+ Network *network;
+ _cleanup_free_ char *name = NULL;
+ _cleanup_free_ char *e = NULL;
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(interface);
+ assert(m);
+ assert(found);
+
+ if (sscanf(path, "/org/freedesktop/network1/network/%ms", &name) != 1)
+ return 0;
+
+ e = bus_label_unescape(name);
+ if (!e)
+ return -ENOMEM;
+
+ r = network_get_by_name(m, e, &network);
+ if (r < 0)
+ return 0;
+
+ *found = network;
+
+ return 1;
+}
diff --git a/src/network/networkd.h b/src/network/networkd.h
index d144c11..147b21a 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -104,7 +104,6 @@ struct Network {
char *match_driver;
char *match_type;
char *match_name;
- char *dhcp_vendor_class_identifier;
Condition *match_host;
Condition *match_virt;
@@ -116,6 +115,7 @@ struct Network {
NetDev *bond;
Hashmap *stacked_netdevs;
AddressFamilyBoolean dhcp;
+ char *dhcp_vendor_class_identifier;
bool dhcp_dns;
bool dhcp_ntp;
bool dhcp_mtu;
@@ -321,6 +321,11 @@ int config_parse_vxlan_group_address(const char *unit,
void *data,
void *userdata);
+extern const sd_bus_vtable network_vtable[];
+
+int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
+int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
+
/* gperf */
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length);
commit dbffab87f1504abc9f189dd253111693c99fbd9a
Author: Tom Gundersen <teg at jklm.no>
Date: Sun Feb 8 13:29:35 2015 +0100
networkd: add network_get_by_name
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 8dfe437..e2c8a23 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -481,6 +481,8 @@ void manager_free(Manager *m) {
while ((network = m->networks))
network_free(network);
+ hashmap_free(m->networks_by_name);
+
while ((netdev = hashmap_first(m->netdevs)))
netdev_unref(netdev);
hashmap_free(m->netdevs);
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 4589162..504419c 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -34,6 +34,7 @@
static int network_load_one(Manager *manager, const char *filename) {
_cleanup_network_free_ Network *network = NULL;
_cleanup_fclose_ FILE *file = NULL;
+ char *d;
Route *route;
Address *address;
int r;
@@ -84,6 +85,18 @@ static int network_load_one(Manager *manager, const char *filename) {
if (!network->filename)
return log_oom();
+ network->name = strdup(basename(filename));
+ if (!network->name)
+ return log_oom();
+
+ d = strrchr(network->name, '.');
+ if (!d)
+ return -EINVAL;
+
+ assert(streq(d, ".network"));
+
+ *d = '\0';
+
network->dhcp = ADDRESS_FAMILY_NO;
network->dhcp_ntp = true;
network->dhcp_dns = true;
@@ -115,6 +128,14 @@ static int network_load_one(Manager *manager, const char *filename) {
LIST_PREPEND(networks, manager->networks, network);
+ r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = hashmap_put(manager->networks_by_name, network->name, network);
+ if (r < 0)
+ return r;
+
LIST_FOREACH(routes, route, network->static_routes) {
if (!route->family) {
log_warning("Route section without Gateway field configured in %s. "
@@ -210,8 +231,15 @@ void network_free(Network *network) {
hashmap_free(network->routes_by_section);
hashmap_free(network->fdb_entries_by_section);
- if (network->manager && network->manager->networks)
- LIST_REMOVE(networks, network->manager->networks, network);
+ if (network->manager) {
+ if (network->manager->networks)
+ LIST_REMOVE(networks, network->manager->networks, network);
+
+ if (network->manager->networks_by_name)
+ hashmap_remove(network->manager->networks_by_name, network->name);
+ }
+
+ free(network->name);
condition_free_list(network->match_host);
condition_free_list(network->match_virt);
@@ -221,6 +249,22 @@ void network_free(Network *network) {
free(network);
}
+int network_get_by_name(Manager *manager, const char *name, Network **ret) {
+ Network *network;
+
+ assert(manager);
+ assert(name);
+ assert(ret);
+
+ network = hashmap_get(manager->networks_by_name, name);
+ if (!network)
+ return -ENOENT;
+
+ *ret = network;
+
+ return 0;
+}
+
int network_get(Manager *manager, struct udev_device *device,
const char *ifname, const struct ether_addr *address,
Network **ret) {
diff --git a/src/network/networkd.h b/src/network/networkd.h
index cd54e9b..d144c11 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -97,6 +97,7 @@ struct Network {
Manager *manager;
char *filename;
+ char *name;
struct ether_addr *match_mac;
char *match_path;
@@ -224,6 +225,7 @@ struct Manager {
Hashmap *links;
Hashmap *netdevs;
+ Hashmap *networks_by_name;
LIST_HEAD(Network, networks);
LIST_HEAD(AddressPool, address_pools);
@@ -265,6 +267,7 @@ void network_free(Network *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
#define _cleanup_network_free_ _cleanup_(network_freep)
+int network_get_by_name(Manager *manager, const char *name, Network **ret);
int network_get(Manager *manager, struct udev_device *device,
const char *ifname, const struct ether_addr *mac,
Network **ret);
commit 23cb977ac382931a0b5c1385cdbb7fe5c4c92b1a
Author: Tom Gundersen <teg at jklm.no>
Date: Sun Feb 8 19:43:01 2015 +0100
build-sys: properly enable the networkd dbus activation
diff --git a/Makefile.am b/Makefile.am
index d289914..3dc5fa0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5688,6 +5688,12 @@ GENERAL_ALIASES += \
$(systemunitdir)/systemd-networkd.service $(pkgsysconfdir)/system/multi-user.target.wants/systemd-networkd.service \
$(systemunitdir)/systemd-networkd-wait-online.service $(pkgsysconfdir)/system/network-online.target.wants/systemd-networkd-wait-online.service
+SYSTEM_UNIT_ALIASES += \
+ systemd-networkd.service dbus-org.freedesktop.network1.service
+
+BUSNAMES_TARGET_WANTS += \
+ org.freedesktop.network1.busname
+
EXTRA_DIST += \
src/network/networkd-network-gperf.gperf \
src/network/networkd-netdev-gperf.gperf \
commit c149ae08ccbc63279c0b2d146b6879163dfffce3
Author: Tom Gundersen <teg at jklm.no>
Date: Sun Feb 8 19:31:46 2015 +0100
sd-rtnl: add support for IFLA_INET6_*
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c
index 4ef698a..f2d5c8d 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -265,6 +265,30 @@ static const NLTypeSystemUnion rtnl_prot_info_type_system_union = {
.match_type = NL_MATCH_PROTOCOL,
};
+static const struct NLType rtnl_af_spec_inet6_types[IFLA_INET6_MAX + 1] = {
+ [IFLA_INET6_FLAGS] = { .type = NLA_U32 },
+/*
+ IFLA_INET6_CONF,
+ IFLA_INET6_STATS,
+ IFLA_INET6_MCAST,
+ IFLA_INET6_CACHEINFO,
+ IFLA_INET6_ICMP6STATS,
+*/
+ [IFLA_INET6_TOKEN] = { .type = NLA_IN_ADDR },
+ [IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 },
+};
+
+static const NLTypeSystem rtnl_af_spec_type_systems[AF_MAX] = {
+ [AF_INET6] = { .max = ELEMENTSOF(rtnl_af_spec_inet6_types) - 1,
+ .types = rtnl_af_spec_inet6_types },
+};
+
+static const NLTypeSystemUnion rtnl_af_spec_type_system_union = {
+ .num = AF_MAX,
+ .type_systems = rtnl_af_spec_type_systems,
+ .match_type = NL_MATCH_PROTOCOL,
+};
+
static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
[IFLA_ADDRESS] = { .type = NLA_ETHER_ADDR, },
[IFLA_BROADCAST] = { .type = NLA_ETHER_ADDR, },
@@ -298,7 +322,9 @@ static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
[IFLA_STATS64],
[IFLA_VF_PORTS] = { .type = NLA_NESTED },
[IFLA_PORT_SELF] = { .type = NLA_NESTED },
- [IFLA_AF_SPEC] = { .type = NLA_NESTED },
+*/
+ [IFLA_AF_SPEC] = { .type = NLA_NESTED, .type_system_union = &rtnl_af_spec_type_system_union },
+/*
[IFLA_VF_PORTS],
[IFLA_PORT_SELF],
[IFLA_AF_SPEC],
commit 4af7b60d428765c2d2c66c46f416f6dae55e9ddb
Author: Tom Gundersen <teg at jklm.no>
Date: Sun Feb 8 12:37:05 2015 +0100
sd-rtnl: extend type system to allow address-family to decide the union members
So far we only supported selecting them by sibling attributes.
(This stuff is all a bit crazy, but there seems to be no other way...)
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 14a52df..276591f 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -609,6 +609,49 @@ int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
return 0;
}
+int sd_rtnl_message_get_family(sd_rtnl_message *m, int *family) {
+ assert_return(m, -EINVAL);
+ assert_return(family, -EINVAL);
+
+ assert(m->hdr);
+
+ if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) {
+ struct ifinfomsg *ifi;
+
+ ifi = NLMSG_DATA(m->hdr);
+
+ *family = ifi->ifi_family;
+
+ return 0;
+ } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) {
+ struct rtmsg *rtm;
+
+ rtm = NLMSG_DATA(m->hdr);
+
+ *family = rtm->rtm_family;
+
+ return 0;
+ } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) {
+ struct ndmsg *ndm;
+
+ ndm = NLMSG_DATA(m->hdr);
+
+ *family = ndm->ndm_family;
+
+ return 0;
+ } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) {
+ struct ifaddrmsg *ifa;
+
+ ifa = NLMSG_DATA(m->hdr);
+
+ *family = ifa->ifa_family;
+
+ return 0;
+ }
+
+ return -ENOTSUP;
+}
+
int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
assert_return(m, -EINVAL);
@@ -898,16 +941,37 @@ int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
r = message_attribute_has_type(m, type, NLA_NESTED);
- if (r < 0)
- return r;
- else
+ if (r < 0) {
+ const NLTypeSystemUnion *type_system_union;
+ int family;
+
+ r = message_attribute_has_type(m, type, NLA_UNION);
+ if (r < 0)
+ return r;
+ size = (size_t) r;
+
+ r = sd_rtnl_message_get_family(m, &family);
+ if (r < 0)
+ return r;
+
+ r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
+ if (r < 0)
+ return r;
+
+ r = type_system_union_protocol_get_type_system(type_system_union,
+ &m->container_type_system[m->n_containers + 1],
+ family);
+ if (r < 0)
+ return r;
+ } else {
size = (size_t)r;
- r = type_system_get_type_system(m->container_type_system[m->n_containers],
- &m->container_type_system[m->n_containers + 1],
- type);
- if (r < 0)
- return r;
+ r = type_system_get_type_system(m->container_type_system[m->n_containers],
+ &m->container_type_system[m->n_containers + 1],
+ type);
+ if (r < 0)
+ return r;
+ }
r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
if (r < 0)
@@ -1181,7 +1245,6 @@ int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
return r;
} else if (nl_type->type == NLA_UNION) {
const NLTypeSystemUnion *type_system_union;
- const char *key;
r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
&type_system_union,
@@ -1189,15 +1252,42 @@ int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
if (r < 0)
return r;
- r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
- if (r < 0)
- return r;
+ switch (type_system_union->match_type) {
+ case NL_MATCH_SIBLING:
+ {
+ const char *key;
- r = type_system_union_get_type_system(type_system_union,
- &type_system,
- key);
- if (r < 0)
- return r;
+ r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
+ if (r < 0)
+ return r;
+
+ r = type_system_union_get_type_system(type_system_union,
+ &type_system,
+ key);
+ if (r < 0)
+ return r;
+
+ break;
+ }
+ case NL_MATCH_PROTOCOL:
+ {
+ int family;
+
+ r = sd_rtnl_message_get_family(m, &family);
+ if (r < 0)
+ return r;
+
+ r = type_system_union_protocol_get_type_system(type_system_union,
+ &type_system,
+ family);
+ if (r < 0)
+ return r;
+
+ break;
+ }
+ default:
+ assert_not_reached("sd-rtnl: invalid type system union type");
+ }
} else
return -EINVAL;
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c
index d4abe4c..4ef698a 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -224,6 +224,7 @@ static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
.num = _NL_UNION_LINK_INFO_DATA_MAX,
.lookup = nl_union_link_info_data_from_string,
.type_systems = rtnl_link_info_data_type_systems,
+ .match_type = NL_MATCH_SIBLING,
.match = IFLA_INFO_KIND,
};
@@ -242,7 +243,7 @@ static const NLTypeSystem rtnl_link_info_type_system = {
.types = rtnl_link_info_types,
};
-static const struct NLType rtnl_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
+static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_STATE] = { .type = NLA_U8 },
[IFLA_BRPORT_COST] = { .type = NLA_U32 },
[IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
@@ -253,9 +254,15 @@ static const struct NLType rtnl_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
};
-static const NLTypeSystem rtnl_bridge_port_type_system = {
- .max = ELEMENTSOF(rtnl_bridge_port_types) - 1,
- .types = rtnl_bridge_port_types,
+static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = {
+ [AF_BRIDGE] = { .max = ELEMENTSOF(rtnl_prot_info_bridge_port_types) - 1,
+ .types = rtnl_prot_info_bridge_port_types },
+};
+
+static const NLTypeSystemUnion rtnl_prot_info_type_system_union = {
+ .num = AF_MAX,
+ .type_systems = rtnl_prot_info_type_systems,
+ .match_type = NL_MATCH_PROTOCOL,
};
static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
@@ -273,9 +280,8 @@ static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
[IFLA_MASTER] = { .type = NLA_U32 },
/*
[IFLA_WIRELESS],
- [IFLA_PROTINFO],
*/
- [IFLA_PROTINFO] = { .type = NLA_NESTED, .type_system = &rtnl_bridge_port_type_system },
+ [IFLA_PROTINFO] = { .type = NLA_UNION, .type_system_union = &rtnl_prot_info_type_system_union },
[IFLA_TXQLEN] = { .type = NLA_U32 },
/*
[IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
@@ -463,6 +469,7 @@ int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union
int type;
assert(type_system_union);
+ assert_return(type_system_union->match_type == NL_MATCH_SIBLING, -EINVAL);
assert(type_system_union->lookup);
assert(type_system_union->type_systems);
assert(ret);
@@ -478,3 +485,25 @@ int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union
return 0;
}
+
+int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol) {
+ const NLTypeSystem *type_system;
+
+ assert(type_system_union);
+ assert(type_system_union->type_systems);
+ assert(ret);
+ assert_return(type_system_union->match_type == NL_MATCH_PROTOCOL, -EINVAL);
+ assert_return(protocol < type_system_union->num, -EINVAL);
+
+ if (protocol >= type_system_union->num)
+ return -ENOTSUP;
+
+ type_system = &type_system_union->type_systems[protocol];
+
+ if (!type_system)
+ return -ENOTSUP;
+
+ *ret = type_system;
+
+ return 0;
+}
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.h b/src/libsystemd/sd-rtnl/rtnl-types.h
index 9c0dc30..1ab9444 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.h
+++ b/src/libsystemd/sd-rtnl/rtnl-types.h
@@ -36,12 +36,18 @@ enum {
NLA_UNION,
};
+typedef enum NLMatchType {
+ NL_MATCH_SIBLING,
+ NL_MATCH_PROTOCOL,
+} NLMatchType;
+
typedef struct NLTypeSystemUnion NLTypeSystemUnion;
typedef struct NLTypeSystem NLTypeSystem;
typedef struct NLType NLType;
struct NLTypeSystemUnion {
int num;
+ NLMatchType match_type;
uint16_t match;
int (*lookup)(const char *);
const NLTypeSystem *type_systems;
@@ -63,6 +69,7 @@ int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, ui
int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type);
int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type);
int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key);
+int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol);
typedef enum NLUnionLinkInfoData {
NL_UNION_LINK_INFO_DATA_BOND,
diff --git a/src/libsystemd/sd-rtnl/test-rtnl.c b/src/libsystemd/sd-rtnl/test-rtnl.c
index ed60b3c..02f7a8e 100644
--- a/src/libsystemd/sd-rtnl/test-rtnl.c
+++ b/src/libsystemd/sd-rtnl/test-rtnl.c
@@ -31,8 +31,26 @@
#include "missing.h"
#include "rtnl-internal.h"
+static void test_message_link_bridge(sd_rtnl *rtnl) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL;
+ uint32_t cost;
+
+ assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
+ assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0);
+ assert_se(sd_rtnl_message_open_container(message, IFLA_PROTINFO) >= 0);
+ assert_se(sd_rtnl_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0);
+ assert_se(sd_rtnl_message_close_container(message) >= 0);
+
+ assert_se(sd_rtnl_message_rewind(message) >= 0);
+
+ assert_se(sd_rtnl_message_enter_container(message, IFLA_PROTINFO) >= 0);
+ assert_se(sd_rtnl_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0);
+ assert_se(cost == 10);
+ assert_se(sd_rtnl_message_exit_container(message) >= 0);
+}
+
static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
- _cleanup_rtnl_message_unref_ sd_rtnl_message *message;
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL;
const char *mac = "98:fe:94:3f:c6:18", *name = "test";
char buffer[ETHER_ADDR_TO_STRING_MAX];
unsigned int mtu = 1450, mtu_out;
@@ -394,6 +412,8 @@ int main(void) {
test_get_addresses(rtnl);
+ test_message_link_bridge(rtnl);
+
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
assert_se(m);
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index 0eb5547..be318e5 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -88,6 +88,8 @@ int sd_rtnl_message_get_errno(sd_rtnl_message *m);
int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type);
int sd_rtnl_message_is_broadcast(sd_rtnl_message *m);
+int sd_rtnl_message_get_family(sd_rtnl_message *m, int *family);
+
int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen);
int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope);
int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags);
More information about the systemd-commits
mailing list