Skip to content

Commit

Permalink
feat(networkd): add ipv6 ra overrides (LP: #1973222) (#461)
Browse files Browse the repository at this point in the history
Providing a new "ra-overrides" YAML setting:

  accept-ra: true
  ra-overrides:
    use-routes: false
    use-domains: false
    table: 127

COMMITS:
* feat(networkd): add ipv6 ra overrides
* refactor(networkd): use tristate for use_dns and enum for use_domains
* chore(networkd): make if statement more readable
* chore(docs): typo
* chore(docs): add older system path to rt_tables
* chore(docs): refine description for table in ipv6-ra-overrides
* chore(networkd): rename route_table to table
* chore(test): remove unnecessary workaround
* chore(abi): move ipv6_ra_overrides down
* refactor(parse): reuse handle_generic_bool function
* test(networkd): test ra overrides with all fields
* docs(networkd): remove confusing documentation
* refactor(parse): remove handle_generic_use_domains
* chore(networkd): rename ipv6_ra_overrides to ra_overrides
* fix struct ipv6_overrides -> ra_overrides naming
* doc: describe default value for ra-overrides.use-domains
  • Loading branch information
KhooHaoYit authored Jun 6, 2024
1 parent 1e1d80c commit 44b2a5c
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 22 deletions.
34 changes: 34 additions & 0 deletions doc/netplan-yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ Match devices by MAC when setting options like: `wakeonlan` or `*-offload`.
> respond to Router Advertisements. If unset use the host kernel default
> setting.

- **`ra-overrides`** (mapping)

> (networkd back end only) Overrides default IPv6 Router Advertisement (RA)
> behaviour; see the `IPv6 Router Advertisement Overrides` section below.

- **`addresses`** (sequence of scalars and mappings)

> Add static addresses to the interface in addition to the ones received
Expand Down Expand Up @@ -697,6 +702,35 @@ client processes as specified in the Netplan YAML.
>
> **Requires feature: `dhcp-use-domains`**

## IPv6 Router Advertisement Overrides
Overrides for IPv6 Router Advertisement (RA) behaviour (only supported with
networkd back end).

- **`ra-overrides`** (mapping)

> The `ra-overrides` mappings override the default IPv6 Router
> Advertisement behaviour.

- **`use-dns`** (boolean)

> Default: `true`. When `true`, the DNS servers received from the
> Router Advertisement will be used. Currently only has an effect
> on the networkd back end.

- **`use-domains`** (scalar)

> Takes a boolean, or the special value `route`. When true, the domain
> name received from the Router Advertisement will be used as DNS search
> domain over this link. If set to `route`, the domain name received
> from the IPv6 RA will be used for routing DNS queries only, but not
> for searching. Defaults to `false`.

- **`table`** (scalar)

> The routing table number for routes received in the IPv6 RA.
> Allowed values are positive integers starting from 1.
> Some values are already in use to refer to specific routing tables:
> see `{/etc,/usr/share}/iproute2/rt_tables`.

## Routing

Expand Down
58 changes: 37 additions & 21 deletions src/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,35 @@ typedef enum {
NETPLAN_OPTIONAL_STATIC = 1<<4,
} NetplanOptionalAddressFlag;

typedef enum
{
/**
* @brief Tristate enum type
*
* This type defines a boolean which can be unset, i.e.
* this type has three states. The enum is ordered so
* that
*
* UNSET -> -1
* FALSE -> 0
* TRUE -> 1
*
* And the integer values can be used directly when
* converting to string.
*/
NETPLAN_TRISTATE_UNSET = -1, /* -1 */
NETPLAN_TRISTATE_FALSE, /* 0 */
NETPLAN_TRISTATE_TRUE, /* 1 */
} NetplanTristate;

typedef enum
{
NETPLAN_USE_DOMAIN_MODE_UNSET = -1,
NETPLAN_USE_DOMAIN_MODE_FALSE,
NETPLAN_USE_DOMAIN_MODE_TRUE,
NETPLAN_USE_DOMAIN_MODE_ROUTE,
} NetplanUseDomainMode;

/* Fields below are valid for dhcp4 and dhcp6 unless otherwise noted. */
typedef struct dhcp_overrides {
gboolean use_dns;
Expand All @@ -45,6 +74,12 @@ typedef struct dhcp_overrides {
guint metric;
} NetplanDHCPOverrides;

typedef struct ra_overrides {
NetplanTristate use_dns;
NetplanUseDomainMode use_domains;
guint table;
} NetplanRAOverrides;

typedef enum {
NETPLAN_RA_MODE_KERNEL,
NETPLAN_RA_MODE_ENABLED,
Expand Down Expand Up @@ -179,27 +214,6 @@ typedef struct netplan_backend_settings {
GData* passthrough; /* See g_datalist* functions */
} NetplanBackendSettings;

typedef enum
{
/**
* @brief Tristate enum type
*
* This type defines a boolean which can be unset, i.e.
* this type has three states. The enum is ordered so
* that
*
* UNSET -> -1
* FALSE -> 0
* TRUE -> 1
*
* And the integer values can be used directly when
* converting to string.
*/
NETPLAN_TRISTATE_UNSET = -1, /* -1 */
NETPLAN_TRISTATE_FALSE, /* 0 */
NETPLAN_TRISTATE_TRUE, /* 1 */
} NetplanTristate;

typedef struct netplan_vxlan NetplanVxlan;

/* Keep 'struct netplan_net_definition' in a separate header file, to allow for
Expand Down Expand Up @@ -414,4 +428,6 @@ struct netplan_net_definition {

NetplanTristate bridge_hairpin;
NetplanTristate bridge_learning;

NetplanRAOverrides ra_overrides;
};
25 changes: 25 additions & 0 deletions src/netplan.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,30 @@ write_dhcp_overrides(yaml_event_t* event, yaml_emitter_t* emitter, const char* k
err_path: return FALSE; // LCOV_EXCL_LINE
}

STATIC gboolean
write_ra_overrides(yaml_event_t* event, yaml_emitter_t* emitter, const char* key, const NetplanNetDefinition* def, const NetplanRAOverrides* data)
{
if (DIRTY_COMPLEX(def, *data)
|| data->use_dns != NETPLAN_TRISTATE_UNSET
|| data->use_domains != NETPLAN_USE_DOMAIN_MODE_UNSET
|| data->table != NETPLAN_ROUTE_TABLE_UNSPEC) {
YAML_SCALAR_PLAIN(event, emitter, key);
YAML_MAPPING_OPEN(event, emitter);
YAML_BOOL_TRISTATE(def, event, emitter, "use-dns", data->use_dns);
if (data->use_domains == NETPLAN_USE_DOMAIN_MODE_FALSE) {
YAML_STRING_PLAIN(def, event, emitter, "use-domains", "false");
} else if (data->use_domains == NETPLAN_USE_DOMAIN_MODE_TRUE) {
YAML_STRING_PLAIN(def, event, emitter, "use-domains", "true");
} else if (data->use_domains == NETPLAN_USE_DOMAIN_MODE_ROUTE) {
YAML_STRING_PLAIN(def, event, emitter, "use-domains", "route");
}
YAML_UINT_DEFAULT(def, event, emitter, "table", data->table, NETPLAN_ROUTE_TABLE_UNSPEC);
YAML_MAPPING_CLOSE(event, emitter);
}
return TRUE;
err_path: return FALSE; // LCOV_EXCL_LINE
}

STATIC gboolean
write_tunnel_settings(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNetDefinition* def)
{
Expand Down Expand Up @@ -772,6 +796,7 @@ _serialize_yaml(
} else if (def->accept_ra == NETPLAN_RA_MODE_DISABLED) {
YAML_NONNULL_STRING_PLAIN(event, emitter, "accept-ra", "false");
}
write_ra_overrides(event, emitter, "ra-overrides", def, &def->ra_overrides);

YAML_STRING(def, event, emitter, "macaddress", def->set_mac);
YAML_STRING(def, event, emitter, "set-name", def->set_name);
Expand Down
31 changes: 31 additions & 0 deletions src/networkd.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,18 @@ interval_has_suffix(const char* param) {
return TRUE;
}

STATIC gboolean
ra_overrides_is_dirty(const NetplanRAOverrides* overrides) {
if(overrides->use_dns != NETPLAN_TRISTATE_UNSET)
return TRUE;
if(overrides->use_domains != NETPLAN_USE_DOMAIN_MODE_UNSET)
return TRUE;
if(overrides->table != NETPLAN_ROUTE_TABLE_UNSPEC)
return TRUE;

return FALSE;
}


STATIC void
write_bond_parameters(const NetplanNetDefinition* def, GString* s)
Expand Down Expand Up @@ -1059,6 +1071,25 @@ _netplan_netdef_write_network_file(
g_string_append_printf(network, "\n[IPoIB]\nMode=%s\n", netplan_infiniband_mode_name(def->ib_mode));
}

/* ra-overrides */
if (ra_overrides_is_dirty(&def->ra_overrides)) {
g_string_append(network, "\n[IPv6AcceptRA]\n");

if (def->ra_overrides.use_dns != NETPLAN_TRISTATE_UNSET) {
g_string_append_printf(network, "UseDNS=%s\n", def->ra_overrides.use_dns ? "true" : "false");
}
if (def->ra_overrides.use_domains == NETPLAN_USE_DOMAIN_MODE_FALSE) {
g_string_append_printf(network, "UseDomains=%s\n", "false");
} else if (def->ra_overrides.use_domains == NETPLAN_USE_DOMAIN_MODE_TRUE) {
g_string_append_printf(network, "UseDomains=%s\n", "true");
} else if (def->ra_overrides.use_domains == NETPLAN_USE_DOMAIN_MODE_ROUTE) {
g_string_append_printf(network, "UseDomains=%s\n", "route");
}
if (def->ra_overrides.table != NETPLAN_ROUTE_TABLE_UNSPEC) {
g_string_append_printf(network, "RouteTable=%d\n", def->ra_overrides.table);
}
}

if (network->len > 0 || link->len > 0) {
s = g_string_sized_new(200);
append_match_section(def, s, TRUE);
Expand Down
43 changes: 42 additions & 1 deletion src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ handle_generic_datalist(NetplanParser *npp, yaml_node_t* node, const char* key_p
return TRUE;
}


/**
* Generic handler for setting a npp->current.netdef string field from a scalar node
* @data: offset into NetplanNetDefinition where the const char* field to write is
Expand Down Expand Up @@ -682,7 +683,7 @@ handle_netdef_bool(NetplanParser* npp, yaml_node_t* node, const void* data, GErr
}

/**
* Generic handler for tri-state settings that can bei "UNSET", "TRUE", or "FALSE".
* Generic handler for tri-state settings that can be "UNSET", "TRUE", or "FALSE".
* @data: offset into NetplanNetDefinition where the guint field to write is located
*/
STATIC gboolean
Expand Down Expand Up @@ -800,6 +801,38 @@ handle_netdef_backend_settings_str(NetplanParser* npp, yaml_node_t* node, const
return handle_generic_str(npp, node, npp->current.netdef, data, error);
}

/**
* Generic handler for setting a npp->current.netdef use-domains field from a scalar node
* @data: offset into NetplanNetDefinition where the use-domains field to write is located
*/
STATIC gboolean
handle_netdef_use_domains(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
NetplanUseDomainMode v;
guint offset = GPOINTER_TO_UINT(data);
NetplanUseDomainMode* dest = ((void*) npp->current.netdef + offset);

gboolean ret = handle_generic_bool(npp, node, npp->current.netdef, data, NULL);

if (ret) {
if (*dest) {
v = NETPLAN_USE_DOMAIN_MODE_TRUE;
} else {
v = NETPLAN_USE_DOMAIN_MODE_FALSE;
}
} else if (g_ascii_strcasecmp(scalar(node), "route") == 0) {
v = NETPLAN_USE_DOMAIN_MODE_ROUTE;
} else {
return yaml_error(npp, node, error,
"Invalid use-domains options '%s', must be a boolean, or the special value 'route'.",
scalar(node));
}

*dest = v;
mark_data_as_dirty(npp, dest);
return TRUE;
}

/*
* Check if the passthrough key format is incorrect and remove it from the list.
* user_data is expected to contain a pointer to the GData list.
Expand Down Expand Up @@ -2876,6 +2909,13 @@ static const mapping_entry_handler dhcp6_overrides_handlers[] = {
{NULL},
};

static const mapping_entry_handler ra_overrides_handlers[] = {
{"use-dns", YAML_SCALAR_NODE, {.generic=handle_netdef_tristate}, netdef_offset(ra_overrides.use_dns)},
{"use-domains", YAML_SCALAR_NODE, {.generic=handle_netdef_use_domains}, netdef_offset(ra_overrides.use_domains)},
{"table", YAML_SCALAR_NODE, {.generic=handle_netdef_guint}, netdef_offset(ra_overrides.table)},
{NULL},
};

/* Handlers shared by all link types */
#define COMMON_LINK_HANDLERS \
{"accept-ra", YAML_SCALAR_NODE, {.generic=handle_accept_ra}, netdef_offset(accept_ra)}, \
Expand All @@ -2888,6 +2928,7 @@ static const mapping_entry_handler dhcp6_overrides_handlers[] = {
{"dhcp-identifier", YAML_SCALAR_NODE, {.generic=handle_dhcp_identifier}, NULL}, \
{"dhcp4-overrides", YAML_MAPPING_NODE, {.map={.handlers=dhcp4_overrides_handlers}}, NULL}, \
{"dhcp6-overrides", YAML_MAPPING_NODE, {.map={.handlers=dhcp6_overrides_handlers}}, NULL}, \
{"ra-overrides", YAML_MAPPING_NODE, {.map={.handlers=ra_overrides_handlers}}, NULL}, \
{"gateway4", YAML_SCALAR_NODE, {.generic=handle_gateway4}, NULL}, \
{"gateway6", YAML_SCALAR_NODE, {.generic=handle_gateway6}, NULL}, \
{"ipv6-address-generation", YAML_SCALAR_NODE, {.generic=handle_netdef_addrgen}, NULL}, \
Expand Down
9 changes: 9 additions & 0 deletions src/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ reset_dhcp_overrides(NetplanDHCPOverrides* overrides)
overrides->metric = NETPLAN_METRIC_UNSPEC;
}

STATIC void
reset_ra_overrides(NetplanRAOverrides* overrides)
{
overrides->use_dns = NETPLAN_TRISTATE_UNSET;
overrides->use_domains = NETPLAN_USE_DOMAIN_MODE_UNSET;
overrides->table = NETPLAN_ROUTE_TABLE_UNSPEC;
}

void
reset_ip_rule(NetplanIPRule* ip_rule)
{
Expand Down Expand Up @@ -236,6 +244,7 @@ reset_netdef(NetplanNetDefinition* netdef, NetplanDefType new_type, NetplanBacke
reset_dhcp_overrides(&netdef->dhcp4_overrides);
reset_dhcp_overrides(&netdef->dhcp6_overrides);
netdef->accept_ra = NETPLAN_RA_MODE_KERNEL;
reset_ra_overrides(&netdef->ra_overrides);

free_garray_with_destructor(&netdef->ip4_addresses, g_free);
free_garray_with_destructor(&netdef->ip6_addresses, g_free);
Expand Down
Loading

0 comments on commit 44b2a5c

Please sign in to comment.