]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: expose Describe Varlink, use for networkctl list & status
authorAnton Tiurin <noxiouz@meta.com>
Mon, 8 Sep 2025 19:31:23 +0000 (12:31 -0700)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 7 Nov 2025 15:08:00 +0000 (00:08 +0900)
Both `list` and `status` with `--json=pretty|short` show the description.
It is fetched via D-Bus by org.freedesktop.network1.Manager.Describe

This change exposes the same data via Varlink API `io.systemd.Network.Describe`
and migrates networkctl list and status commands to use Varlink API.

Update GetStates IDL to use enums for link states.

src/network/networkctl-description.c
src/network/networkd-manager-varlink.c
src/shared/varlink-io.systemd.Network.c
src/shared/varlink-io.systemd.Network.h
src/test/test-varlink-idl.c
test/units/TEST-74-AUX-UTILS.varlinkctl.sh

index fd6cbd78817b86dda83da7292dcae8aef4765977..ec4bebbd6520562d43bc6f44294030118d33460d 100644 (file)
@@ -1,11 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include "sd-bus.h"
+#include "sd-varlink.h"
 
 #include "alloc-util.h"
-#include "bus-error.h"
-#include "bus-locator.h"
-#include "bus-util.h"
 #include "glob-util.h"
 #include "json-util.h"
 #include "log.h"
 #include "networkctl-util.h"
 #include "stdio-util.h"
 #include "strv.h"
+#include "varlink-util.h"
 
-static int get_description(sd_bus *bus, sd_json_variant **ret) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        const char *text;
+static int dump_manager_description(sd_varlink *vl) {
+        sd_json_variant *v;
         int r;
 
-        assert(bus);
-        assert(ret);
+        assert(vl);
 
-        r = bus_call_method(bus, bus_network_mgr, "Describe", &error, &reply, NULL);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get description: %s", bus_error_message(&error, r));
-
-        r = sd_bus_message_read(reply, "s", &text);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        r = sd_json_parse(text, 0, ret, NULL, NULL);
-        if (r < 0)
-                return log_error_errno(r, "Failed to parse JSON: %m");
-
-        return 0;
-}
-
-static int dump_manager_description(sd_bus *bus) {
-        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
-        int r;
-
-        assert(bus);
-
-        r = get_description(bus, &v);
+        r = varlink_call_and_log(vl, "io.systemd.Network.Describe", /* parameters = */ NULL, &v);
         if (r < 0)
                 return r;
 
-        sd_json_variant_dump(v, arg_json_format_flags, NULL, NULL);
+        r = sd_json_variant_dump(v, arg_json_format_flags, /* f = */ NULL, /* prefix = */ NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to dump json object: %m");
         return 0;
 }
 
-static int dump_link_description(sd_bus *bus, char * const *patterns) {
-        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+static int dump_link_description(sd_varlink *vl, char * const *patterns) {
         _cleanup_free_ bool *matched_patterns = NULL;
-        sd_json_variant *i;
+        sd_json_variant *i, *v;
         size_t c = 0;
         int r;
 
-        assert(bus);
+        assert(vl);
         assert(patterns);
 
-        r = get_description(bus, &v);
+        r = varlink_call_and_log(vl, "io.systemd.Network.Describe", /* parameters = */ NULL, &v);
         if (r < 0)
                 return r;
 
@@ -122,20 +97,20 @@ static int dump_link_description(sd_bus *bus, char * const *patterns) {
 }
 
 int dump_description(int argc, char *argv[]) {
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_(sd_varlink_flush_close_unrefp) sd_varlink *vl = NULL;
         int r;
 
         if (!sd_json_format_enabled(arg_json_format_flags))
                 return 0;
 
-        r = acquire_bus(&bus);
+        r = varlink_connect_networkd(&vl);
         if (r < 0)
                 return r;
 
         if (arg_all || argc <= 1)
-                r = dump_manager_description(bus);
+                r = dump_manager_description(vl);
         else
-                r = dump_link_description(bus, strv_skip(argv, 1));
+                r = dump_link_description(vl, strv_skip(argv, 1));
         if (r < 0)
                 return r;
 
index 1697efd771d0a0d9634a87c4befef3541d38239b..055c0902b3badb2ebeeeab9851a1ac44e86a6f84 100644 (file)
@@ -12,6 +12,7 @@
 #include "lldp-rx-internal.h"
 #include "network-util.h"
 #include "networkd-dhcp-server.h"
+#include "networkd-json.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
 #include "networkd-manager-varlink.h"
 #include "varlink-io.systemd.service.h"
 #include "varlink-util.h"
 
+static int vl_method_describe(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+        Manager *m = ASSERT_PTR(userdata);
+        int r;
+
+        assert(parameters);
+        assert(link);
+
+        r = sd_varlink_dispatch(link, parameters, /* dispatch_table = */ NULL, /* userdata = */ NULL);
+        if (r != 0)
+                return r;
+
+        r = manager_build_json(m, &v);
+        if (r < 0)
+                return log_error_errno(r, "Failed to format JSON data: %m");
+
+        return sd_varlink_reply(link, v);
+}
+
 static int vl_method_get_states(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
         Manager *m = ASSERT_PTR(userdata);
         int r;
@@ -288,6 +308,7 @@ int manager_connect_varlink(Manager *m, int fd) {
 
         r = sd_varlink_server_bind_method_many(
                         s,
+                        "io.systemd.Network.Describe",             vl_method_describe,
                         "io.systemd.Network.GetStates",            vl_method_get_states,
                         "io.systemd.Network.GetNamespaceId",       vl_method_get_namespace_id,
                         "io.systemd.Network.GetLLDPNeighbors",     vl_method_get_lldp_neighbors,
index fd8ba3c085f153e65f0e06b8e817e164dd107c1c..27a8db562f6b52e4b86c5562c4a78bd047a82cf7 100644 (file)
 
 #include "varlink-io.systemd.Network.h"
 
-static SD_VARLINK_DEFINE_METHOD(
-                GetStates,
-                SD_VARLINK_DEFINE_OUTPUT(AddressState, SD_VARLINK_STRING, 0),
-                SD_VARLINK_DEFINE_OUTPUT(IPv4AddressState, SD_VARLINK_STRING, 0),
-                SD_VARLINK_DEFINE_OUTPUT(IPv6AddressState, SD_VARLINK_STRING, 0),
-                SD_VARLINK_DEFINE_OUTPUT(CarrierState, SD_VARLINK_STRING, 0),
-                SD_VARLINK_DEFINE_OUTPUT(OnlineState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
-                SD_VARLINK_DEFINE_OUTPUT(OperationalState, SD_VARLINK_STRING, 0));
+static SD_VARLINK_DEFINE_ENUM_TYPE(
+                LinkState,
+                SD_VARLINK_DEFINE_ENUM_VALUE(pending),
+                SD_VARLINK_DEFINE_ENUM_VALUE(initialized),
+                SD_VARLINK_DEFINE_ENUM_VALUE(configuring),
+                SD_VARLINK_DEFINE_ENUM_VALUE(configured),
+                SD_VARLINK_DEFINE_ENUM_VALUE(unmanaged),
+                SD_VARLINK_DEFINE_ENUM_VALUE(failed),
+                SD_VARLINK_DEFINE_ENUM_VALUE(linger));
 
-static SD_VARLINK_DEFINE_METHOD(
-                GetNamespaceId,
-                SD_VARLINK_DEFINE_OUTPUT(NamespaceId, SD_VARLINK_INT, 0),
-                SD_VARLINK_DEFINE_OUTPUT(NamespaceNSID, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+SD_VARLINK_DEFINE_ENUM_TYPE(
+                LinkAddressState,
+                SD_VARLINK_DEFINE_ENUM_VALUE(off),
+                SD_VARLINK_DEFINE_ENUM_VALUE(degraded),
+                SD_VARLINK_DEFINE_ENUM_VALUE(routable));
+
+SD_VARLINK_DEFINE_ENUM_TYPE(
+                LinkOnlineState,
+                SD_VARLINK_DEFINE_ENUM_VALUE(offline),
+                SD_VARLINK_DEFINE_ENUM_VALUE(partial),
+                SD_VARLINK_DEFINE_ENUM_VALUE(online));
+
+SD_VARLINK_DEFINE_ENUM_TYPE(
+                LinkRequiredAddressFamily,
+                SD_VARLINK_DEFINE_ENUM_VALUE(any),
+                SD_VARLINK_DEFINE_ENUM_VALUE(ipv4),
+                SD_VARLINK_DEFINE_ENUM_VALUE(ipv6),
+                SD_VARLINK_DEFINE_ENUM_VALUE(both));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                RoutingPolicyRule,
+                SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
+                SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Source address prefix to match"),
+                SD_VARLINK_DEFINE_FIELD(FromPrefix, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Length of source prefix in bits"),
+                SD_VARLINK_DEFINE_FIELD(FromPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Destination address prefix to match"),
+                SD_VARLINK_DEFINE_FIELD(ToPrefix, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Length of destination prefix in bits"),
+                SD_VARLINK_DEFINE_FIELD(ToPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"),
+                SD_VARLINK_DEFINE_FIELD(Protocol, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable routing protocol name"),
+                SD_VARLINK_DEFINE_FIELD(ProtocolString, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Type of Service (TOS) field to match"),
+                SD_VARLINK_DEFINE_FIELD(TOS, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Rule action type (FR_ACT_* value)"),
+                SD_VARLINK_DEFINE_FIELD(Type, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable rule action type"),
+                SD_VARLINK_DEFINE_FIELD(TypeString, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("IP protocol number to match"),
+                SD_VARLINK_DEFINE_FIELD(IPProtocol, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable IP protocol name"),
+                SD_VARLINK_DEFINE_FIELD(IPProtocolString, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Rule priority (lower value means higher priority)"),
+                SD_VARLINK_DEFINE_FIELD(Priority, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Firewall mark value to match"),
+                SD_VARLINK_DEFINE_FIELD(FirewallMark, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Firewall mark mask to apply"),
+                SD_VARLINK_DEFINE_FIELD(FirewallMask, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Routing table number to use"),
+                SD_VARLINK_DEFINE_FIELD(Table, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Human-readable routing table name"),
+                SD_VARLINK_DEFINE_FIELD(TableString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Whether rule matching is inverted"),
+                SD_VARLINK_DEFINE_FIELD(Invert, SD_VARLINK_BOOL, 0),
+                SD_VARLINK_FIELD_COMMENT("Suppress route lookup if prefix length is less than or equal to this value"),
+                SD_VARLINK_DEFINE_FIELD(SuppressPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Suppress route lookup if interface group matches"),
+                SD_VARLINK_DEFINE_FIELD(SuppressInterfaceGroup, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Source port range to match [start, end]"),
+                SD_VARLINK_DEFINE_FIELD(SourcePort, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Destination port range to match [start, end]"),
+                SD_VARLINK_DEFINE_FIELD(DestinationPort, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("User ID range to match [start, end]"),
+                SD_VARLINK_DEFINE_FIELD(User, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Incoming interface name to match"),
+                SD_VARLINK_DEFINE_FIELD(IncomingInterface, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Outgoing interface name to match"),
+                SD_VARLINK_DEFINE_FIELD(OutgoingInterface, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this rule"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Configuration state of this rule"),
+                SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, 0));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                Route,
+                SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
+                SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Destination network address"),
+                SD_VARLINK_DEFINE_FIELD(Destination, SD_VARLINK_INT, SD_VARLINK_ARRAY),
+                SD_VARLINK_FIELD_COMMENT("Destination network prefix length"),
+                SD_VARLINK_DEFINE_FIELD(DestinationPrefixLength, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Gateway address for this route"),
+                SD_VARLINK_DEFINE_FIELD(Gateway, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Source address prefix for route selection"),
+                SD_VARLINK_DEFINE_FIELD(Source, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Source prefix length"),
+                SD_VARLINK_DEFINE_FIELD(SourcePrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Preferred source address for outgoing packets"),
+                SD_VARLINK_DEFINE_FIELD(PreferredSource, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Type of Service (TOS) field"),
+                SD_VARLINK_DEFINE_FIELD(TOS, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Route scope (RT_SCOPE_* value)"),
+                SD_VARLINK_DEFINE_FIELD(Scope, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable scope string"),
+                SD_VARLINK_DEFINE_FIELD(ScopeString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"),
+                SD_VARLINK_DEFINE_FIELD(Protocol, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable routing protocol name"),
+                SD_VARLINK_DEFINE_FIELD(ProtocolString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Route type (RTN_* value)"),
+                SD_VARLINK_DEFINE_FIELD(Type, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable route type"),
+                SD_VARLINK_DEFINE_FIELD(TypeString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Route priority/metric"),
+                SD_VARLINK_DEFINE_FIELD(Priority, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Routing table number"),
+                SD_VARLINK_DEFINE_FIELD(Table, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable routing table name"),
+                SD_VARLINK_DEFINE_FIELD(TableString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Route flags (RTM_F_* values)"),
+                SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable flags string"),
+                SD_VARLINK_DEFINE_FIELD(FlagsString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Next hop ID for multipath routing"),
+                SD_VARLINK_DEFINE_FIELD(NextHopID, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Maximum Transmission Unit for this route"),
+                SD_VARLINK_DEFINE_FIELD(MTU, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Route preference for IPv6 (low/medium/high)"),
+                SD_VARLINK_DEFINE_FIELD(Preference, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Route lifetime in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this route"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"),
+                SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration state of this route"),
+                SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Interface index for serialization"),
+                SD_VARLINK_DEFINE_FIELD(InterfaceIndex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Route metrics (RTAX_* values)"),
+                SD_VARLINK_DEFINE_FIELD(Metrics, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("TCP congestion control algorithm for this route"),
+                SD_VARLINK_DEFINE_FIELD(TCPCongestionControlAlgorithm, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                NextHopGroup,
+                SD_VARLINK_FIELD_COMMENT("Next hop identifier in the multipath group"),
+                SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Weight for load balancing (higher means more traffic)"),
+                SD_VARLINK_DEFINE_FIELD(Weight, SD_VARLINK_INT, 0));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                NextHop,
+                SD_VARLINK_FIELD_COMMENT("Next hop identifier"),
+                SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
+                SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Gateway address for this next hop"),
+                SD_VARLINK_DEFINE_FIELD(Gateway, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Next hop flags (RTNH_F_* values)"),
+                SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Human-readable flags string"),
+                SD_VARLINK_DEFINE_FIELD(FlagsString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"),
+                SD_VARLINK_DEFINE_FIELD(Protocol, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Human-readable routing protocol name"),
+                SD_VARLINK_DEFINE_FIELD(ProtocolString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Whether this is a blackhole next hop (drops packets)"),
+                SD_VARLINK_DEFINE_FIELD(Blackhole, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Multipath group members with weights for load balancing"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(Group, NextHopGroup, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this next hop"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"),
+                SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration state of this next hop"),
+                SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
 
 static SD_VARLINK_DEFINE_STRUCT_TYPE(
                 LLDPNeighbor,
+                SD_VARLINK_FIELD_COMMENT("Chassis identifier in human-readable format"),
                 SD_VARLINK_DEFINE_FIELD(ChassisID, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Raw chassis identifier bytes"),
                 SD_VARLINK_DEFINE_FIELD(RawChassisID, SD_VARLINK_INT, SD_VARLINK_ARRAY),
-                SD_VARLINK_DEFINE_FIELD(PortID, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Port identifier in human-readable format"),
+                SD_VARLINK_DEFINE_FIELD(PortID, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Raw port identifier bytes"),
                 SD_VARLINK_DEFINE_FIELD(RawPortID, SD_VARLINK_INT, SD_VARLINK_ARRAY),
+                SD_VARLINK_FIELD_COMMENT("Description of the port"),
                 SD_VARLINK_DEFINE_FIELD(PortDescription, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("System name of the LLDP neighbor"),
                 SD_VARLINK_DEFINE_FIELD(SystemName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("System description of the LLDP neighbor"),
                 SD_VARLINK_DEFINE_FIELD(SystemDescription, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
-                SD_VARLINK_DEFINE_FIELD(EnabledCapabilities, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Enabled capabilities bitmap (bridge, router, WLAN, etc.)"),
+                SD_VARLINK_DEFINE_FIELD(EnabledCapabilities, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Manufacturer Usage Description URL (RFC8520)"),
+                SD_VARLINK_DEFINE_FIELD(MUDURL, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("VLAN identifier"),
                 SD_VARLINK_DEFINE_FIELD(VlanID, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
 
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DNS,
+                SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
+                SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("DNS server IP address"),
+                SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY),
+                SD_VARLINK_FIELD_COMMENT("DNS server port number"),
+                SD_VARLINK_DEFINE_FIELD(Port, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Interface index for link-local DNS servers"),
+                SD_VARLINK_DEFINE_FIELD(InterfaceIndex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DNS server hostname for DoT/DoH"),
+                SD_VARLINK_DEFINE_FIELD(ServerName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this DNS server"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"),
+                SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                NTP,
+                SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"),
+                SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("NTP server IP address"),
+                SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("NTP server"),
+                SD_VARLINK_DEFINE_FIELD(Server, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this NTP server"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"),
+                SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                SIP,
+                SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"),
+                SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("SIP server IP address"),
+                SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("SIP server domain name"),
+                SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this SIP server"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"),
+                SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                Domain,
+                SD_VARLINK_FIELD_COMMENT("DNS search or route domain name"),
+                SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this domain"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"),
+                SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DNSSECNegativeTrustAnchor,
+                SD_VARLINK_FIELD_COMMENT("Domain name for which DNSSEC validation is disabled"),
+                SD_VARLINK_DEFINE_FIELD(DNSSECNegativeTrustAnchor, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this negative trust anchor"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DNSSetting,
+                SD_VARLINK_FIELD_COMMENT("Link-Local Multicast Name Resolution setting"),
+                SD_VARLINK_DEFINE_FIELD(LLMNR, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Multicast DNS setting"),
+                SD_VARLINK_DEFINE_FIELD(MDNS, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Whether this connection can be used as a default route for DNS lookups"),
+                SD_VARLINK_DEFINE_FIELD(DNSDefaultRoute, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DNS-over-TLS mode setting"),
+                SD_VARLINK_DEFINE_FIELD(DNSOverTLS, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this DNS setting"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                Pref64,
+                SD_VARLINK_FIELD_COMMENT("IPv6 prefix for NAT64/DNS64"),
+                SD_VARLINK_DEFINE_FIELD(Prefix, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Length of the prefix in bits"),
+                SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Lifetime of the prefix in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Address of router that provided this prefix"),
+                SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                NDisc,
+                SD_VARLINK_FIELD_COMMENT("PREF64 (RFC8781) prefixes advertised via IPv6 Router Advertisements"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(PREF64, Pref64, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                Address,
+                SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
+                SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("IP address"),
+                SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY),
+                SD_VARLINK_FIELD_COMMENT("Peer address for point-to-point interfaces"),
+                SD_VARLINK_DEFINE_FIELD(Peer, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Network prefix length"),
+                SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this address"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Address of the configuration provider (DHCP server, router, etc.)"),
+                SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Broadcast address for IPv4 networks"),
+                SD_VARLINK_DEFINE_FIELD(Broadcast, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Address scope (RT_SCOPE_* value)"),
+                SD_VARLINK_DEFINE_FIELD(Scope, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Human-readable scope string"),
+                SD_VARLINK_DEFINE_FIELD(ScopeString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Address flags (IFA_F_* values)"),
+                SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Human-readable flags string"),
+                SD_VARLINK_DEFINE_FIELD(FlagsString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Address label for IPv4"),
+                SD_VARLINK_DEFINE_FIELD(Label, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Preferred lifetime in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(PreferredLifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Preferred lifetime in microseconds (deprecated, for backward compatibility)"),
+                SD_VARLINK_DEFINE_FIELD(PreferredLifetimeUsec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), /* for backward compat */
+                SD_VARLINK_FIELD_COMMENT("Valid lifetime in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(ValidLifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Valid lifetime in microseconds (deprecated, for backward compatibility)"),
+                SD_VARLINK_DEFINE_FIELD(ValidLifetimeUsec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), /* for backward compat */
+                SD_VARLINK_FIELD_COMMENT("Configuration state of this address"),
+                SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                Neighbor,
+                SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
+                SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("IP address of the neighbor"),
+                SD_VARLINK_DEFINE_FIELD(Destination, SD_VARLINK_INT, SD_VARLINK_ARRAY),
+                SD_VARLINK_FIELD_COMMENT("Link layer (MAC) address of the neighbor"),
+                SD_VARLINK_DEFINE_FIELD(LinkLayerAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY),
+                SD_VARLINK_FIELD_COMMENT("Configuration source for this neighbor entry"),
+                SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Configuration state of this neighbor entry"),
+                SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, 0));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DHCPLease,
+                SD_VARLINK_FIELD_COMMENT("Timestamp when the lease was acquired in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(LeaseTimestampUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("T1 timeout (lease renewal time) in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(Timeout1USec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("T2 timeout (lease rebinding time) in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(Timeout2USec, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                PrivateOption,
+                SD_VARLINK_FIELD_COMMENT("DHCP option number"),
+                SD_VARLINK_DEFINE_FIELD(Option, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Raw data of the private DHCP option"),
+                SD_VARLINK_DEFINE_FIELD(PrivateOptionData, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DHCPv6ClientPD,
+                SD_VARLINK_FIELD_COMMENT("Delegated IPv6 prefix"),
+                SD_VARLINK_DEFINE_FIELD(Prefix, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Length of the delegated prefix in bits"),
+                SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Preferred lifetime of the prefix in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(PreferredLifetimeUsec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Valid lifetime of the prefix in microseconds"),
+                SD_VARLINK_DEFINE_FIELD(ValidLifetimeUsec, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DHCPv6ClientVendorOption,
+                SD_VARLINK_FIELD_COMMENT("IANA enterprise number identifying the vendor"),
+                SD_VARLINK_DEFINE_FIELD(EnterpriseId, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Vendor-specific sub-option code"),
+                SD_VARLINK_DEFINE_FIELD(SubOptionCode, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Raw data of the vendor-specific sub-option"),
+                SD_VARLINK_DEFINE_FIELD(SubOptionData, SD_VARLINK_STRING, 0));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DHCPv6Client,
+                SD_VARLINK_FIELD_COMMENT("DHCPv6 lease information including timestamps and timeouts"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(Lease, DHCPLease, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Delegated prefixes received from DHCPv6 server"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(Prefixes, DHCPv6ClientPD, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Vendor-specific options received in DHCPv6 response"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(VendorSpecificOptions, DHCPv6ClientVendorOption, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DHCP Unique Identifier (DUID) of the client"),
+                SD_VARLINK_DEFINE_FIELD(DUID, SD_VARLINK_INT, SD_VARLINK_ARRAY));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DHCPServerLease,
+                SD_VARLINK_FIELD_COMMENT("DHCP client identifier"),
+                SD_VARLINK_DEFINE_FIELD(ClientId, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Address assigned to the client"),
+                SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Hostname provided by the DHCP client"),
+                SD_VARLINK_DEFINE_FIELD(Hostname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Hardware address type (ARPHRD_* value)"),
+                SD_VARLINK_DEFINE_FIELD(HardwareAddressType, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Length of hardware address in bytes"),
+                SD_VARLINK_DEFINE_FIELD(HardwareAddressLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Hardware (MAC) address of the DHCP client"),
+                SD_VARLINK_DEFINE_FIELD(HardwareAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Lease expiration time in monotonic microseconds"),
+                SD_VARLINK_DEFINE_FIELD(ExpirationUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Lease expiration time in realtime microseconds"),
+                SD_VARLINK_DEFINE_FIELD(ExpirationRealtimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                DHCPServer,
+                SD_VARLINK_FIELD_COMMENT("Offset from the network address for the DHCP address pool"),
+                SD_VARLINK_DEFINE_FIELD(PoolOffset, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Size of the DHCP address pool"),
+                SD_VARLINK_DEFINE_FIELD(PoolSize, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Active DHCP leases assigned by the server"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(Leases, DHCPServerLease, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Static DHCP leases configured for specific clients"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(StaticLeases, DHCPServerLease, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+                Interface,
+                SD_VARLINK_FIELD_COMMENT("Network interface index"),
+                SD_VARLINK_DEFINE_FIELD(Index, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Primary interface name"),
+                SD_VARLINK_DEFINE_FIELD(Name, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Alternative interface names"),
+                SD_VARLINK_DEFINE_FIELD(AlternativeNames, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Interface index of the master device (for bridge/bond slaves)"),
+                SD_VARLINK_DEFINE_FIELD(MasterInterfaceIndex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Interface kind (vlan, bridge, bond, etc.)"),
+                SD_VARLINK_DEFINE_FIELD(Kind, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Interface type (ether, loopback, etc.)"),
+                SD_VARLINK_DEFINE_FIELD(Type, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Kernel driver name"),
+                SD_VARLINK_DEFINE_FIELD(Driver, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Interface flags (IFF_* values)"),
+                SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable interface flags"),
+                SD_VARLINK_DEFINE_FIELD(FlagsString, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Kernel operational state (IF_OPER_* value)"),
+                SD_VARLINK_DEFINE_FIELD(KernelOperationalState, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Human-readable kernel operational state"),
+                SD_VARLINK_DEFINE_FIELD(KernelOperationalStateString, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Current MTU in bytes"),
+                SD_VARLINK_DEFINE_FIELD(MTU, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Minimum allowed MTU in bytes"),
+                SD_VARLINK_DEFINE_FIELD(MinimumMTU, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Maximum allowed MTU in bytes"),
+                SD_VARLINK_DEFINE_FIELD(MaximumMTU, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Current hardware (MAC) address"),
+                SD_VARLINK_DEFINE_FIELD(HardwareAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Permanent hardware (MAC) address from factory"),
+                SD_VARLINK_DEFINE_FIELD(PermanentHardwareAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Broadcast address for Ethernet interfaces"),
+                SD_VARLINK_DEFINE_FIELD(BroadcastAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("IPv6 link-local address"),
+                SD_VARLINK_DEFINE_FIELD(IPv6LinkLocalAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Wireless LAN interface type (NL80211_IFTYPE_* value)"),
+                SD_VARLINK_DEFINE_FIELD(WirelessLanInterfaceType, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Human-readable wireless LAN interface type"),
+                SD_VARLINK_DEFINE_FIELD(WirelessLanInterfaceTypeString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Wireless network SSID"),
+                SD_VARLINK_DEFINE_FIELD(SSID, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Wireless access point BSSID (MAC address)"),
+                SD_VARLINK_DEFINE_FIELD(BSSID, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Administrative state (configuring, configured, etc.)"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(AdministrativeState, LinkState, 0),
+                SD_VARLINK_FIELD_COMMENT("Operational state (routable, degraded, etc.)"),
+                SD_VARLINK_DEFINE_FIELD(OperationalState, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Carrier state (carrier, no-carrier, etc.)"),
+                SD_VARLINK_DEFINE_FIELD(CarrierState, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Address configuration state"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(AddressState, LinkAddressState, 0),
+                SD_VARLINK_FIELD_COMMENT("IPv4 address configuration state"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(IPv4AddressState, LinkAddressState, 0),
+                SD_VARLINK_FIELD_COMMENT("IPv6 address configuration state"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(IPv6AddressState, LinkAddressState, 0),
+                SD_VARLINK_FIELD_COMMENT("Online state (online, offline, etc.)"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(OnlineState, LinkOnlineState, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Path to .network configuration file"),
+                SD_VARLINK_DEFINE_FIELD(NetworkFile, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Paths to .network drop-in configuration files"),
+                SD_VARLINK_DEFINE_FIELD(NetworkFileDropins, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Whether this interface is required for online state"),
+                SD_VARLINK_DEFINE_FIELD(RequiredForOnline, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Required operational state range for considering interface online [min, max]"),
+                SD_VARLINK_DEFINE_FIELD(RequiredOperationalStateForOnline, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Required address family for considering interface online"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(RequiredFamilyForOnline, LinkRequiredAddressFamily, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Activation policy (up, always-up, manual, etc.)"),
+                SD_VARLINK_DEFINE_FIELD(ActivationPolicy, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Path to .netdev configuration file"),
+                SD_VARLINK_DEFINE_FIELD(NetDevFile, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Paths to .netdev drop-in configuration files"),
+                SD_VARLINK_DEFINE_FIELD(NetDevFileDropins, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Path to .link configuration file"),
+                SD_VARLINK_DEFINE_FIELD(LinkFile, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Paths to .link drop-in configuration files"),
+                SD_VARLINK_DEFINE_FIELD(LinkFileDropins, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Device path in sysfs"),
+                SD_VARLINK_DEFINE_FIELD(Path, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Hardware vendor name"),
+                SD_VARLINK_DEFINE_FIELD(Vendor, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Hardware model name"),
+                SD_VARLINK_DEFINE_FIELD(Model, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DNS servers configured for this interface"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(DNS, DNS, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                /* FIXME: DNR Addresses fied (json array or arrays) is incompatible with Varlink type system */
+                SD_VARLINK_FIELD_COMMENT("Discovery of Network-designated Resolvers (RFC9463)"),
+                SD_VARLINK_DEFINE_FIELD(DNR, SD_VARLINK_OBJECT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("NTP servers configured for this interface"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(NTP, NTP, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("SIP servers configured for this interface"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(SIP, SIP, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DNS search domains"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(SearchDomains, Domain, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DNS route-only domains"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(RouteDomains, Domain, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DNSSEC negative trust anchors"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(DNSSECNegativeTrustAnchors, DNSSECNegativeTrustAnchor, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DNS resolution settings (LLMNR, mDNS, etc.)"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(DNSSettings, DNSSetting, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Captive portal detection URL (RFC8910)"),
+                SD_VARLINK_DEFINE_FIELD(CaptivePortal, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("IPv6 Neighbor Discovery information"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(NDisc, NDisc, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("IP addresses configured on this interface"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(Addresses, Address, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Neighbor entries (ARP/NDP cache)"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(Neighbors, Neighbor, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Next hops for multipath routing"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(NextHops, NextHop, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Routes configured on this interface"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(Routes, Route, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DHCP server configuration and leases"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(DHCPServer, DHCPServer, SD_VARLINK_NULLABLE),
+                /* FIXME: DHCPv4Client has 6rdPrefix field that is incompatible with Varlink naming */
+                SD_VARLINK_FIELD_COMMENT("DHCPv4 client configuration and lease information"),
+                SD_VARLINK_DEFINE_FIELD(DHCPv4Client, SD_VARLINK_OBJECT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("DHCPv6 client configuration and lease information"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(DHCPv6Client, DHCPv6Client, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("LLDP neighbors discovered on this interface"),
+                SD_VARLINK_DEFINE_FIELD_BY_TYPE(LLDP, LLDPNeighbor, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_METHOD(
+                Describe,
+                SD_VARLINK_FIELD_COMMENT("All network interfaces managed by systemd-networkd"),
+                SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(Interfaces, Interface, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("All configured next hops for multipath routing"),
+                SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(NextHops, NextHop, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("All configured routes across all interfaces"),
+                SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(Routes, Route, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("All configured routing policy rules"),
+                SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(RoutingPolicyRules, RoutingPolicyRule, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_METHOD(
+                GetStates,
+                SD_VARLINK_FIELD_COMMENT("Overall address configuration state across all interfaces"),
+                SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(AddressState, LinkAddressState, 0),
+                SD_VARLINK_FIELD_COMMENT("IPv4 address configuration state across all interfaces"),
+                SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(IPv4AddressState, LinkAddressState, 0),
+                SD_VARLINK_FIELD_COMMENT("IPv6 address configuration state across all interfaces"),
+                SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(IPv6AddressState, LinkAddressState, 0),
+                SD_VARLINK_FIELD_COMMENT("Carrier state across all interfaces"),
+                SD_VARLINK_DEFINE_OUTPUT(CarrierState, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Online state across all interfaces"),
+                SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(OnlineState, LinkOnlineState, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Operational state across all interfaces"),
+                SD_VARLINK_DEFINE_OUTPUT(OperationalState, SD_VARLINK_STRING, 0));
+
+static SD_VARLINK_DEFINE_METHOD(
+                GetNamespaceId,
+                SD_VARLINK_FIELD_COMMENT("Network namespace inode number"),
+                SD_VARLINK_DEFINE_OUTPUT(NamespaceId, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Network namespace ID (cookie) assigned by the kernel"),
+                SD_VARLINK_DEFINE_OUTPUT(NamespaceNSID, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+
 static SD_VARLINK_DEFINE_STRUCT_TYPE(
                 LLDPNeighborsByInterface,
+                SD_VARLINK_FIELD_COMMENT("Network interface index"),
                 SD_VARLINK_DEFINE_FIELD(InterfaceIndex, SD_VARLINK_INT, 0),
+                SD_VARLINK_FIELD_COMMENT("Primary interface name"),
                 SD_VARLINK_DEFINE_FIELD(InterfaceName, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("Alternative interface names"),
                 SD_VARLINK_DEFINE_FIELD(InterfaceAlternativeNames, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("LLDP neighbors discovered on this interface"),
                 SD_VARLINK_DEFINE_FIELD_BY_TYPE(Neighbors, LLDPNeighbor, SD_VARLINK_ARRAY));
 
 static SD_VARLINK_DEFINE_METHOD(
                 GetLLDPNeighbors,
+                SD_VARLINK_FIELD_COMMENT("Filter by interface index (optional)"),
                 SD_VARLINK_DEFINE_INPUT(InterfaceIndex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Filter by interface name (optional)"),
                 SD_VARLINK_DEFINE_INPUT(InterfaceName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("LLDP neighbors grouped by interface"),
                 SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(Neighbors, LLDPNeighborsByInterface, SD_VARLINK_ARRAY));
 
 static SD_VARLINK_DEFINE_METHOD(
                 SetPersistentStorage,
+                SD_VARLINK_FIELD_COMMENT("Whether persistent storage is ready and writable"),
                 SD_VARLINK_DEFINE_INPUT(Ready, SD_VARLINK_BOOL, 0));
 
 static SD_VARLINK_DEFINE_ERROR(StorageReadOnly);
@@ -50,10 +609,37 @@ static SD_VARLINK_DEFINE_ERROR(StorageReadOnly);
 SD_VARLINK_DEFINE_INTERFACE(
                 io_systemd_Network,
                 "io.systemd.Network",
+                &vl_method_Describe,
                 &vl_method_GetStates,
                 &vl_method_GetNamespaceId,
                 &vl_method_GetLLDPNeighbors,
                 &vl_method_SetPersistentStorage,
+                &vl_type_Address,
+                &vl_type_DHCPLease,
+                &vl_type_DHCPServer,
+                &vl_type_DHCPServerLease,
+                &vl_type_DHCPv6Client,
+                &vl_type_DHCPv6ClientPD,
+                &vl_type_DHCPv6ClientVendorOption,
+                &vl_type_DNS,
+                &vl_type_DNSSECNegativeTrustAnchor,
+                &vl_type_DNSSetting,
+                &vl_type_Domain,
+                &vl_type_Interface,
+                &vl_type_LinkState,
+                &vl_type_LinkAddressState,
+                &vl_type_LinkOnlineState,
+                &vl_type_LinkRequiredAddressFamily,
                 &vl_type_LLDPNeighbor,
                 &vl_type_LLDPNeighborsByInterface,
+                &vl_type_NDisc,
+                &vl_type_Neighbor,
+                &vl_type_NextHop,
+                &vl_type_NextHopGroup,
+                &vl_type_NTP,
+                &vl_type_Pref64,
+                &vl_type_PrivateOption,
+                &vl_type_Route,
+                &vl_type_RoutingPolicyRule,
+                &vl_type_SIP,
                 &vl_error_StorageReadOnly);
index 1d2871636f97113408e70e0d1a43a511d74079e3..6d727cd9ee8c7fdb77ab75c4844c480fb08c4686 100644 (file)
@@ -4,3 +4,6 @@
 #include "sd-varlink-idl.h"
 
 extern const sd_varlink_interface vl_interface_io_systemd_Network;
+extern const sd_varlink_symbol vl_type_LinkAddressState;
+extern const sd_varlink_symbol vl_type_LinkOnlineState;
+extern const sd_varlink_symbol vl_type_LinkRequiredAddressFamily;
index c449d1b3c00c8194a1f49cc602b996bb29799fd4..cc2481a0847d63c8e96dfb4e9137416cd4af4d77 100644 (file)
@@ -11,6 +11,7 @@
 #include "dissect-image.h"
 #include "fd-util.h"
 #include "json-util.h"
+#include "network-util.h"
 #include "pretty-print.h"
 #include "tests.h"
 #include "varlink-idl-util.h"
@@ -512,6 +513,12 @@ TEST(enums_idl) {
         TEST_IDL_ENUM(BootEntryType, boot_entry_type, vl_type_BootEntryType);
         TEST_IDL_ENUM_TO_STRING(BootEntrySource, boot_entry_source, vl_type_BootEntrySource);
         TEST_IDL_ENUM(PartitionDesignator, partition_designator, vl_type_PartitionDesignator);
+        TEST_IDL_ENUM(LinkAddressState, link_address_state, vl_type_LinkAddressState);
+        TEST_IDL_ENUM_TO_STRING(LinkAddressState, link_address_state, vl_type_LinkAddressState);
+        TEST_IDL_ENUM(LinkOnlineState, link_online_state, vl_type_LinkOnlineState);
+        TEST_IDL_ENUM_TO_STRING(LinkOnlineState, link_online_state, vl_type_LinkOnlineState);
+        TEST_IDL_ENUM(AddressFamily, link_required_address_family, vl_type_LinkRequiredAddressFamily);
+        TEST_IDL_ENUM_TO_STRING(AddressFamily, link_required_address_family, vl_type_LinkRequiredAddressFamily);
 }
 
 DEFINE_TEST_MAIN(LOG_DEBUG);
index 6f5f90e1feab0330cd1bffd512dd01e3b1085783..a35097ffa7a4e69fb6b2217a2d1b26ee7c7ae001 100755 (executable)
@@ -185,6 +185,11 @@ varlinkctl info /run/systemd/io.systemd.Manager
 varlinkctl introspect /run/systemd/io.systemd.Manager io.systemd.Manager
 varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Manager.Describe '{}'
 
+# test io.systemd.Network
+varlinkctl info /run/systemd/netif/io.systemd.Network
+varlinkctl introspect /run/systemd/netif/io.systemd.Network io.systemd.Network
+varlinkctl call /run/systemd/netif/io.systemd.Network io.systemd.Network.Describe '{}'
+
 # test io.systemd.Unit
 varlinkctl info /run/systemd/io.systemd.Manager
 varlinkctl introspect /run/systemd/io.systemd.Manager io.systemd.Unit