/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "varlink-io.systemd.Network.h"

/* Helper macro to define address fields with both binary and string representation */
#define VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \
        SD_VARLINK_FIELD_COMMENT(comment), \
        SD_VARLINK_DEFINE_FIELD(field_name, SD_VARLINK_INT, SD_VARLINK_ARRAY | (flags)), \
        SD_VARLINK_FIELD_COMMENT(comment " (human-readable format)"), \
        SD_VARLINK_DEFINE_FIELD(field_name##String, SD_VARLINK_STRING, (flags))

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));

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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE),
                SD_VARLINK_FIELD_COMMENT("Length of source prefix in bits"),
                SD_VARLINK_DEFINE_FIELD(FromPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0),
                SD_VARLINK_FIELD_COMMENT("Destination network prefix length"),
                SD_VARLINK_DEFINE_FIELD(DestinationPrefixLength, SD_VARLINK_INT, 0),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Source, "Source address prefix for route selection", SD_VARLINK_NULLABLE),
                SD_VARLINK_FIELD_COMMENT("Source prefix length"),
                SD_VARLINK_DEFINE_FIELD(SourcePrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", 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_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_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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0),
                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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", 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("Human-readable IPv6 prefix"),
                SD_VARLINK_DEFINE_FIELD(PrefixString, SD_VARLINK_STRING, 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Peer, "Peer address for point-to-point interfaces", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider (DHCP server, router, etc.)", SD_VARLINK_NULLABLE),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Broadcast, "Broadcast address for IPv4 networks", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0),
                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),
                SD_VARLINK_FIELD_COMMENT("Hostname received from DHCP server"),
                SD_VARLINK_DEFINE_FIELD(Hostname, SD_VARLINK_STRING, 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("Human-readable delegated IPv6 prefix"),
                SD_VARLINK_DEFINE_FIELD(PrefixString, SD_VARLINK_STRING, 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", 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),
                VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", 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 field (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 transmit configuration for this interface"),
                SD_VARLINK_DEFINE_FIELD_BY_TYPE(LLDP, LLDPNeighbor, 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);

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);
