Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,61 @@ fun getAllAIGeneratedValidators(): Map<Validator, OptionValueInformation> {
Validator("config_parse_unit_path_strv_printf", "0") to ConfigParseUnitPathStrvPrintfOptionValue() as OptionValueInformation,
Validator("config_parse_socket_service", "0") to ConfigParseSocketServiceOptionValue() as OptionValueInformation,
Validator("config_parse_service_sockets", "0") to ConfigParseServiceSocketsOptionValue() as OptionValueInformation,
// Batch 2026-10: network-route-addr
// Generic word-list / string / match parsers.
Validator("config_parse_match_strv", "0") to ConfigParseMatchStrvOptionValue() as OptionValueInformation,
Validator("config_parse_strv", "0") to ConfigParseStrvOptionValue() as OptionValueInformation,
Validator("config_parse_match_property", "0") to ConfigParseMatchPropertyOptionValue() as OptionValueInformation,
Validator("config_parse_string", "CONFIG_PARSE_STRING_SAFE_AND_ASCII") to ConfigParseStringSafeAsciiOptionValue() as OptionValueInformation,
Validator("config_parse_nft_set", "NFT_SET_PARSE_NETWORK") to ConfigParseNftSetNetworkOptionValue() as OptionValueInformation,
Validator("config_parse_timezone", "0") to ConfigParseTimezoneOptionValue() as OptionValueInformation,
Validator("config_parse_in_addr_non_null", "AF_INET6") to ConfigParseInAddrNonNullIpv6OptionValue() as OptionValueInformation,
Validator("config_parse_neighbor_proxy_address", "0") to ConfigParseNeighborProxyAddressOptionValue() as OptionValueInformation,
// [Network] stacked netdevs: the ltype only records the expected kind; every slot takes netdev names.
Validator("config_parse_stacked_netdev", "NETDEV_KIND_IPOIB") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "NETDEV_KIND_IPVLAN") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "NETDEV_KIND_IPVTAP") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "NETDEV_KIND_MACSEC") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "NETDEV_KIND_MACVLAN") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "NETDEV_KIND_MACVTAP") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "NETDEV_KIND_VLAN") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "NETDEV_KIND_VXLAN") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "NETDEV_KIND_XFRM") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
Validator("config_parse_stacked_netdev", "_NETDEV_KIND_TUNNEL") to ConfigParseStackedNetdevOptionValue() as OptionValueInformation,
// [IPv6SendRA] / [IPv6Prefix] / [IPv6RoutePrefix] / [IPv6PREF64Prefix] / [IPv6AcceptRA].
Validator("config_parse_router_prefix_delegation", "0") to ConfigParseRouterPrefixDelegationOptionValue() as OptionValueInformation,
Validator("config_parse_router_uint32_msec_usec", "0") to ConfigParseRouterUint32MsecUsecOptionValue() as OptionValueInformation,
Validator("config_parse_router_lifetime", "0") to ConfigParseRouterLifetimeOptionValue() as OptionValueInformation,
Validator("config_parse_router_home_agent_lifetime", "0") to ConfigParseRouterHomeAgentLifetimeOptionValue() as OptionValueInformation,
Validator("config_parse_route_prefix", "0") to ConfigParseRoutePrefixOptionValue() as OptionValueInformation,
Validator("config_parse_route_prefix_lifetime", "0") to ConfigParseRoutePrefixLifetimeOptionValue() as OptionValueInformation,
Validator("config_parse_pref64_prefix_lifetime", "0") to ConfigParsePref64PrefixLifetimeOptionValue() as OptionValueInformation,
// config_parse_prefix_token hands its value straight to config_parse_address_generation_type.
Validator("config_parse_prefix_token", "0") to ConfigParseAddressGenerationTypeOptionValue() as OptionValueInformation,
Validator("config_parse_ndisc_route_metric", "0") to ConfigParseNdiscRouteMetricOptionValue() as OptionValueInformation,
Validator("config_parse_ndisc_route_metric", "AF_INET6") to ConfigParseNdiscRouteMetricOptionValue() as OptionValueInformation,
Validator("config_parse_can_restart_usec", "0") to ConfigParseCanRestartUsecOptionValue() as OptionValueInformation,
// [Route] table slots (each ltype mirrors its own ConfigSectionParser entry).
Validator("config_parse_route_section", "ROUTE_TABLE") to ConfigParseRouteTableOptionValue() as OptionValueInformation,
Validator("config_parse_route_section", "ROUTE_MULTIPATH") to ConfigParseRouteMultiPathOptionValue() as OptionValueInformation,
Validator("config_parse_route_section", "ROUTE_METRIC_MTU") to ConfigParseRouteMetricMtuOptionValue() as OptionValueInformation,
Validator("config_parse_route_section", "ROUTE_METRIC_ADVMSS") to ConfigParseRouteMetricAdvMssOptionValue() as OptionValueInformation,
Validator("config_parse_route_section", "ROUTE_METRIC_INITCWND") to ConfigParseRouteMetricInitCwndOptionValue() as OptionValueInformation,
Validator("config_parse_route_section", "ROUTE_METRIC_RTO_MIN") to ConfigParseRouteMetricTcpRtoOptionValue() as OptionValueInformation,
// [RoutingPolicyRule] table slots.
Validator("config_parse_routing_policy_rule", "ROUTING_POLICY_RULE_TABLE") to ConfigParseRouteTableOptionValue("config_parse_routing_policy_rule") as OptionValueInformation,
Validator("config_parse_routing_policy_rule", "ROUTING_POLICY_RULE_FWMARK") to ConfigParseRoutingPolicyRuleFirewallMarkOptionValue() as OptionValueInformation,
Validator("config_parse_routing_policy_rule", "ROUTING_POLICY_RULE_IP_PROTOCOL") to ConfigParseRoutingPolicyRuleIpProtocolOptionValue() as OptionValueInformation,
Validator("config_parse_routing_policy_rule", "ROUTING_POLICY_RULE_UID_RANGE") to ConfigParseRoutingPolicyRuleUidRangeOptionValue() as OptionValueInformation,
// [Address] / [Neighbor] / [IPv6AddressLabel] table slots.
Validator("config_parse_address_section", "ADDRESS_LABEL") to ConfigParseAddressLabelOptionValue() as OptionValueInformation,
// ADDRESS_NET_LABEL's table entry is config_parse_string with CONFIG_PARSE_STRING_SAFE.
Validator("config_parse_address_section", "ADDRESS_NET_LABEL") to ConfigParseStringOptionValue() as OptionValueInformation,
// ADDRESS_NFT_SET's table entry is config_parse_nft_set with NFT_SET_PARSE_NETWORK.
Validator("config_parse_address_section", "ADDRESS_NFT_SET") to ConfigParseNftSetNetworkOptionValue() as OptionValueInformation,
Validator("config_parse_neighbor_section", "NEIGHBOR_DESTINATION_ADDRESS") to ConfigParseNeighborDestinationAddressOptionValue() as OptionValueInformation,
Validator("config_parse_ipv6_address_label_section", "IPV6_ADDRESS_LABEL_PREFIX") to ConfigParseIpv6AddressLabelPrefixOptionValue() as OptionValueInformation,
Validator("config_parse_ipv6_address_label_section", "IPV6_ADDRESS_LABEL") to ConfigParseIpv6AddressLabelOptionValue() as OptionValueInformation,

)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.EOF
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.RegexTerminal
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.SequenceCombinator

/*
* [Address] Label= (.network).
*
* man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Label=
* parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/networkd-address.c#L2298-L2363 config_parse_address_section (ADDRESS_LABEL)
* https://github.com/systemd/systemd/blob/0f0682b773/src/network/networkd-address.c#L2174-L2200 config_parse_address_label
* leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/socket-util.c#L832-L852 address_label_valid
*/

/**
* Validator for `[Address] Label=` (.network) — the ADDRESS_LABEL slot, whose table entry is
* config_parse_address_label → address_label_valid().
*
* One to 15 characters (shorter than IFNAMSIZ), each a byte in 32…126 — printable ASCII, space
* included. A longer or non-ASCII label is ignored with "Interface label is too long or invalid".
*/
class ConfigParseAddressLabelOptionValue : SimpleGrammarOptionValues(
"config_parse_address_section",
SequenceCombinator(RegexTerminal("""[\s\S]+""", """[\x20-\x7E]{1,15}"""), EOF())
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.EOF
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.SequenceCombinator
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.NETWORK_ROUTE_ADDR_USEC_INFINITY
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.USEC_PER_MSEC
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.divRoundUp
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.timeSpan
import java.math.BigInteger

/*
* [CAN] RestartSec= (.network).
*
* man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#RestartSec=
* parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/networkd-can.c#L210-L245 config_parse_can_restart_usec (0)
* leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1198-L1287 parse_time (via parse_sec)
* leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1147-L1196 extract_multiplier
*/

private val UINT32_MAX: BigInteger = BigInteger.valueOf(4_294_967_295L)

/**
* Validator for `[CAN] RestartSec=` (.network).
*
* config_parse_can_restart_usec reads a time span with parse_sec() and ignores it unless it is
* `infinity` or rounds up to at most UINT32_MAX milliseconds (the kernel's IFLA_CAN_RESTART_MS is a
* u32). `0` (disable automatic restart) is accepted. Note this parser has no isempty() branch of its
* own; an empty assignment is not something this grammar is asked about.
*/
class ConfigParseCanRestartUsecOptionValue : SimpleGrammarOptionValues(
"config_parse_can_restart_usec",
SequenceCombinator(timeSpan { it == NETWORK_ROUTE_ADDR_USEC_INFINITY || divRoundUp(it, USEC_PER_MSEC) <= UINT32_MAX }, EOF())
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.Checked
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.EOF
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.IPV6_ADDR
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.SequenceCombinator
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.ipIsNull
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.ipLiteralBytes

/*
* [Network] IPv6StableSecretAddress= (.network).
*
* man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#IPv6StableSecretAddress=
* parser https://github.com/systemd/systemd/blob/0f0682b773/src/shared/conf-parser.c#L2036-L2082 config_parse_in_addr_non_null (AF_INET6)
* leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/in-addr-util.c#L517-L529 in_addr_from_string
* linux https://man7.org/linux/man-pages/man3/inet_pton.3.html
*/

/**
* Validator for config_parse_in_addr_non_null with ltype AF_INET6 — `[Network]
* IPv6StableSecretAddress=` (.network).
*
* The value goes through in_addr_from_string(AF_INET6), i.e. inet_pton(AF_INET6): an IPv6 literal, no
* prefix length and no `%zone`. An IPv4 literal is not accepted. The parser then refuses the
* all-zero address (`::`, `0:0:0:0:0:0:0:0`, …) with "cannot be the ANY address", which is flagged
* here as well.
*/
class ConfigParseInAddrNonNullIpv6OptionValue : SimpleGrammarOptionValues(
"config_parse_in_addr_non_null",
SequenceCombinator(
Checked(IPV6_ADDR) { text -> ipLiteralBytes(text)?.let { !ipIsNull(it) } ?: false },
EOF()
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.EOF
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.SafeAtoTerminal
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.SequenceCombinator

/*
* [IPv6AddressLabel] Label= (.network).
*
* man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Label=
* parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/networkd-address-label.c#L419-L461 config_parse_ipv6_address_label_section (IPV6_ADDRESS_LABEL)
* https://github.com/systemd/systemd/blob/0f0682b773/src/network/networkd-address-label.c#L386-L417 config_parse_ipv6_address_label
* leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full (base 0)
*/

/**
* Validator for `[IPv6AddressLabel] Label=` (.network): safe_atou32() — decimal, `0x` hex, `0o`/leading
* zero octal, `0b` binary — in 0…4294967294. 4294967295 (0xffffffff) is reserved and refused. The value is
* whole, so whitespace after a `0b`/`0o` prefix (`0b 1`) and a leading `\v` reach safe_atou32 and are fine.
*/
class ConfigParseIpv6AddressLabelOptionValue : SimpleGrammarOptionValues(
"config_parse_ipv6_address_label_section",
SequenceCombinator(
SafeAtoTerminal(
signed = false,
base = 0,
flags = emptySet(),
minInclusive = 0L,
maxInclusive = 4_294_967_294L,
acceptsWhitespace = true,
acceptsMinus = true,
),
EOF()
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.Checked
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.EOF
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.IPV6_PREFIX_SAFE_LEN
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.SafeAtoTerminal
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.SequenceCombinator
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.ipLiteralBytes

/*
* [IPv6AddressLabel] Prefix= (.network).
*
* man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#%5BIPv6AddressLabel%5D%20Section%20Options
* parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/networkd-address-label.c#L419-L461 config_parse_ipv6_address_label_section (IPV6_ADDRESS_LABEL_PREFIX)
* https://github.com/systemd/systemd/blob/0f0682b773/src/network/networkd-address-label.c#L346-L384 config_parse_ipv6_address_label_prefix
* leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/in-addr-util.c#L799-L843 in_addr_prefix_from_string (AF_INET6)
* leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/in-addr-util.c#L165-L171 in6_addr_is_ipv4_mapped_address
* linux https://man7.org/linux/man-pages/man3/inet_pton.3.html (kernel net/ipv6/addrlabel.c ip6addrlbl_alloc)
*/

/** True for an IPv4-mapped address (`::ffff:a.b.c.d`) whose prefix length exceeds 96. */
private fun isMappedTooLong(text: String): Boolean {
val slash = text.indexOf('/')
val bytes = ipLiteralBytes(if (slash >= 0) text.substring(0, slash) else text) ?: return false
val mapped = (0 until 10).all { bytes[it].toInt() == 0 } && bytes[10].toInt() == -1 && bytes[11].toInt() == -1
// The same safe_atou8 reading as the length in IPV6_PREFIX_SAFE_LEN, so `/0b1100001` counts as 97.
val length = if (slash >= 0) {
SafeAtoTerminal(
signed = false,
base = 0,
flags = emptySet(),
minInclusive = 0L,
maxInclusive = 128L,
acceptsWhitespace = true,
acceptsMinus = true,
).valueOf(text.substring(slash + 1))?.toInt() ?: return false
} else {
128
}
return mapped && length > 96
}

/**
* Validator for `[IPv6AddressLabel] Prefix=` (.network).
*
* An IPv6 prefix as in_addr_prefix_from_string(AF_INET6) reads it — an IPv6 literal with an optional
* `/LEN` in 0…128 (no slash means /128). config_parse_ipv6_address_label_prefix then refuses an
* IPv4-mapped address (`::ffff:0:0/96`) with a prefix length above 96, mirroring the kernel's
* ip6addrlbl_alloc(); note that this includes an IPv4-mapped address written without a slash.
*/
class ConfigParseIpv6AddressLabelPrefixOptionValue : SimpleGrammarOptionValues(
"config_parse_ipv6_address_label_section",
SequenceCombinator(Checked(IPV6_PREFIX_SAFE_LEN) { !isMappedTooLong(it) }, EOF())
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.gram
* Validator for ManagedOOMMemoryPressureDurationSec=.
*
* C function: config_parse_managed_oom_mem_pressure_duration_sec in src/core/load-fragment.c.
* Empty resets to USEC_INFINITY. Otherwise calls parse_sec(rvalue) and additionally requires
* Empty resets to NETWORK_ROUTE_ADDR_USEC_INFINITY. Otherwise calls parse_sec(rvalue) and additionally requires
* the result to be at least 1s and strictly less than infinity.
*
* The grammar matches parse_sec syntax (which is the existing TIME_VALUE: "infinity" or a
Expand Down
Loading
Loading