summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abi_compat.c123
-rw-r--r--src/error.c13
-rw-r--r--src/error.h3
-rw-r--r--src/generate.c93
-rw-r--r--src/netplan.c226
-rw-r--r--src/networkd.c3
-rw-r--r--src/parse-globals.h18
-rw-r--r--src/parse-nm.c5
-rw-r--r--src/parse.c1419
-rw-r--r--src/types.c53
-rw-r--r--src/types.h71
-rw-r--r--src/util-internal.h8
-rw-r--r--src/util.c77
-rw-r--r--src/validation.c84
-rw-r--r--src/validation.h6
-rw-r--r--src/yaml-helpers.h20
16 files changed, 1259 insertions, 963 deletions
diff --git a/src/abi_compat.c b/src/abi_compat.c
index dea044a..988fe9c 100644
--- a/src/abi_compat.c
+++ b/src/abi_compat.c
@@ -25,10 +25,12 @@
#include "types.h"
#include "util-internal.h"
#include "parse-nm.h"
+#include "parse-globals.h"
#include "names.h"
#include "networkd.h"
#include "nm.h"
#include "openvswitch.h"
+#include "util.h"
#include <unistd.h>
#include <glib.h>
@@ -59,11 +61,13 @@ char _global_backend_off[8+offsetof(struct netplan_state, backend)] = {};
NETPLAN_ABI
NetplanState global_state = {};
+// LCOV_EXCL_START
NetplanBackend
netplan_get_global_backend()
{
return netplan_state_get_backend(&global_state);
}
+// LCOV_EXCL_STOP
/**
* Clear NetplanNetDefinition hashtable
@@ -73,9 +77,11 @@ netplan_clear_netdefs()
{
guint n = netplan_state_get_netdefs_size(&global_state);
netplan_state_reset(&global_state);
+ netplan_parser_reset(&global_parser);
return n;
}
+// LCOV_EXCL_START
NETPLAN_INTERNAL void
write_network_file(const NetplanNetDefinition* def, const char* rootdir, const char* path)
{
@@ -115,7 +121,6 @@ cleanup_networkd_conf(const char* rootdir)
// There only for compatibility purposes, the proper implementation is now directly
// in the `generate` binary.
-// LCOV_EXCL_START
NETPLAN_ABI void
enable_networkd(const char* generator_dir)
{
@@ -134,7 +139,6 @@ enable_networkd(const char* generator_dir)
exit(1);
}
}
-// LCOV_EXCL_STOP
NETPLAN_INTERNAL void
write_nm_conf(NetplanNetDefinition* def, const char* rootdir)
@@ -181,3 +185,118 @@ cleanup_ovs_conf(const char* rootdir)
{
netplan_ovs_cleanup(rootdir);
}
+// LCOV_EXCL_STOP
+
+gboolean
+netplan_parse_yaml(const char* filename, GError** error)
+{
+ return netplan_parser_load_yaml(&global_parser, filename, error);
+}
+
+/**
+ * Post-processing after parsing all config files
+ */
+GHashTable *
+netplan_finish_parse(GError** error)
+{
+ if (netplan_state_import_parser_results(&global_state, &global_parser, error))
+ return global_state.netdefs;
+ return NULL;
+}
+
+/**
+ * Generate the Netplan YAML configuration for the selected netdef
+ * @def: NetplanNetDefinition (as pointer), the data to be serialized
+ * @rootdir: If not %NULL, generate configuration in this root directory
+ * (useful for testing).
+ */
+void
+write_netplan_conf(const NetplanNetDefinition* def, const char* rootdir)
+{
+ netplan_netdef_write_yaml(&global_state, def, rootdir, NULL);
+}
+
+gboolean
+netplan_state_write_yaml(const NetplanState* np_state, const char* file_hint, const char* rootdir, GError** error);
+
+/**
+ * Generate the Netplan YAML configuration for all currently parsed netdefs
+ * @file_hint: Name hint for the generated output YAML file
+ * @rootdir: If not %NULL, generate configuration in this root directory
+ * (useful for testing).
+ */
+NETPLAN_ABI void
+write_netplan_conf_full(const char* file_hint, const char* rootdir)
+{
+ netplan_finish_parse(NULL);
+ netplan_state_write_yaml(&global_state, file_hint, rootdir, NULL);
+}
+
+NETPLAN_PUBLIC gboolean
+netplan_parse_keyfile(const char* filename, GError** error)
+{
+ return netplan_parser_load_keyfile(&global_parser, filename, error);
+}
+
+// LCOV_EXCL_START
+void process_input_file(const char *f)
+{
+ GError* error = NULL;
+
+ g_debug("Processing input file %s..", f);
+ if (!netplan_parser_load_yaml(&global_parser, f, &error)) {
+ g_fprintf(stderr, "%s\n", error->message);
+ exit(1);
+ }
+}
+
+gboolean
+process_yaml_hierarchy(const char* rootdir)
+{
+ GError* error = NULL;
+ if (!netplan_parser_load_yaml_hierarchy(&global_parser, rootdir, &error)) {
+ g_fprintf(stderr, "%s\n", error->message);
+ exit(1);
+ }
+ return TRUE;
+}
+// LCOV_EXCL_STOP
+
+/**
+ * Helper function for testing only
+ */
+NETPLAN_INTERNAL void
+_write_netplan_conf(const char* netdef_id, const char* rootdir)
+{
+ GHashTable* ht = NULL;
+ const NetplanNetDefinition* def = NULL;
+ ht = netplan_finish_parse(NULL);
+ def = g_hash_table_lookup(ht, netdef_id);
+ write_netplan_conf(def, rootdir);
+}
+
+/**
+ * Get the filename from which the given netdef has been parsed.
+ * @rootdir: ID of the netdef to be looked up
+ * @rootdir: parse files from this root directory
+ */
+gchar*
+netplan_get_filename_by_id(const char* netdef_id, const char* rootdir)
+{
+ NetplanParser* npp = netplan_parser_new();
+ NetplanState* np_state = netplan_state_new();
+ char *filename = NULL;
+ GError* error = NULL;
+
+ if (!netplan_parser_load_yaml_hierarchy(npp, rootdir, &error) ||
+ !netplan_state_import_parser_results(np_state, npp, &error)) {
+ g_fprintf(stderr, "%s\n", error->message);
+ return NULL;
+ }
+ netplan_parser_clear(&npp);
+
+ netplan_state_get_netdef(np_state, netdef_id);
+ filename = g_strdup(netplan_netdef_get_filename(netplan_state_get_netdef(np_state, netdef_id)));
+ netplan_state_clear(&np_state);
+ return filename;
+}
diff --git a/src/error.c b/src/error.c
index ff28be9..85f29ba 100644
--- a/src/error.c
+++ b/src/error.c
@@ -22,8 +22,7 @@
#include <yaml.h>
#include "parse.h"
-#include "parse-globals.h"
-
+#include "types.h"
/****************************************************
* Loading and error handling
@@ -41,10 +40,10 @@ write_error_marker(GString *message, int column)
}
static char *
-get_syntax_error_context(const int line_num, const int column, GError **error)
+get_syntax_error_context(const NetplanParser* npp, const int line_num, const int column, GError **error)
{
GString *message = NULL;
- GFile *cur_file = g_file_new_for_path(current_file);
+ GFile *cur_file = g_file_new_for_path(npp->current.filename);
GFileInputStream *file_stream;
GDataInputStream *stream;
gsize len;
@@ -147,7 +146,7 @@ parser_error(const yaml_parser_t* parser, const char* yaml, GError** error)
* Put a YAML specific error message for @node into @error.
*/
gboolean
-yaml_error(const yaml_node_t* node, GError** error, const char* msg, ...)
+yaml_error(const NetplanParser *npp, const yaml_node_t* node, GError** error, const char* msg, ...)
{
va_list argp;
char* s;
@@ -156,10 +155,10 @@ yaml_error(const yaml_node_t* node, GError** error, const char* msg, ...)
va_start(argp, msg);
g_vasprintf(&s, msg, argp);
if (node != NULL) {
- error_context = get_syntax_error_context(node->start_mark.line, node->start_mark.column, error);
+ error_context = get_syntax_error_context(npp, node->start_mark.line, node->start_mark.column, error);
g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
"%s:%zu:%zu: Error in network definition: %s\n%s",
- current_file,
+ npp->current.filename,
node->start_mark.line + 1,
node->start_mark.column + 1,
s,
diff --git a/src/error.h b/src/error.h
index 68061d8..7f1d9c2 100644
--- a/src/error.h
+++ b/src/error.h
@@ -22,10 +22,11 @@
#include <gio/gio.h>
#include <yaml.h>
+#include "parse.h"
gboolean
parser_error(const yaml_parser_t* parser, const char* yaml, GError** error);
gboolean
-yaml_error(const yaml_node_t* node, GError** error, const char* msg, ...);
+yaml_error(const NetplanParser *npp, const yaml_node_t* node, GError** error, const char* msg, ...);
diff --git a/src/generate.c b/src/generate.c
index bc024db..c15a380 100644
--- a/src/generate.c
+++ b/src/generate.c
@@ -29,7 +29,6 @@
#include "util.h"
#include "util-internal.h"
#include "parse.h"
-#include "parse-globals.h"
#include "names.h"
#include "networkd.h"
#include "nm.h"
@@ -38,7 +37,7 @@
static gchar* rootdir;
static gchar** files;
-static gboolean any_networkd;
+static gboolean any_networkd = FALSE;
static gboolean any_sriov;
static gchar* mapping_iface;
@@ -114,22 +113,8 @@ start_unit_jit(gchar *unit)
};
// LCOV_EXCL_STOP
-static void
-nd_iterator_list(gpointer value, gpointer user_data)
-{
- NetplanNetDefinition* def = (NetplanNetDefinition*) value;
- if (write_networkd_conf(def, (const char*) user_data))
- any_networkd = TRUE;
-
- write_ovs_conf(def, (const char*) user_data);
- write_nm_conf(def, (const char*) user_data);
- if (def->sriov_explicit_vf_count < G_MAXUINT || def->sriov_link)
- any_sriov = TRUE;
-}
-
-
static int
-find_interface(gchar* interface)
+find_interface(gchar* interface, GHashTable* netdefs)
{
GPtrArray *found;
GFileInfo *info;
@@ -204,6 +189,14 @@ exit_find:
return ret;
}
+#define CHECK_CALL(call) {\
+ if (!call) {\
+ error_code = 1; \
+ fprintf(stderr, "%s\n", error->message); \
+ goto cleanup;\
+ }\
+}
+
int main(int argc, char** argv)
{
GError* error = NULL;
@@ -212,6 +205,9 @@ int main(int argc, char** argv)
gboolean called_as_generator = (strstr(argv[0], "systemd/system-generators/") != NULL);
g_autofree char* generator_run_stamp = NULL;
glob_t gl;
+ int error_code = 0;
+ NetplanParser* npp = NULL;
+ NetplanState* np_state = NULL;
/* Parse CLI options */
opt_context = g_option_context_new(NULL);
@@ -226,7 +222,7 @@ int main(int argc, char** argv)
g_option_context_add_main_entries(opt_context, options, NULL);
if (!g_option_context_parse(opt_context, &argc, &argv, &error)) {
- g_fprintf(stderr, "failed to parse options: %s\n", error->message);
+ fprintf(stderr, "failed to parse options: %s\n", error->message);
return 1;
}
@@ -242,34 +238,48 @@ int main(int argc, char** argv)
}
}
+ npp = netplan_parser_new();
/* Read all input files */
if (files && !called_as_generator) {
- for (gchar** f = files; f && *f; ++f)
- process_input_file(*f);
- } else if (!process_yaml_hierarchy(rootdir))
- return 1; // LCOV_EXCL_LINE
-
- netdefs = netplan_finish_parse(&error);
- if (error) {
- g_fprintf(stderr, "%s\n", error->message);
- exit(1);
- }
+ for (gchar** f = files; f && *f; ++f) {
+ CHECK_CALL(netplan_parser_load_yaml(npp, *f, &error));
+ }
+ } else
+ CHECK_CALL(netplan_parser_load_yaml_hierarchy(npp, rootdir, &error));
+
+ np_state = netplan_state_new();
+ CHECK_CALL(netplan_state_import_parser_results(np_state, npp, &error));
/* Clean up generated config from previous runs */
- cleanup_networkd_conf(rootdir);
- cleanup_nm_conf(rootdir);
- cleanup_ovs_conf(rootdir);
+ netplan_networkd_cleanup(rootdir);
+ netplan_nm_cleanup(rootdir);
+ netplan_ovs_cleanup(rootdir);
+
cleanup_sriov_conf(rootdir);
- if (mapping_iface && netdefs)
- return find_interface(mapping_iface);
+ if (mapping_iface && np_state->netdefs) {
+ error_code = find_interface(mapping_iface, np_state->netdefs);
+ goto cleanup;
+ }
/* Generate backend specific configuration files from merged data. */
- write_ovs_conf_finish(rootdir); // OVS cleanup unit is always written
- if (netdefs) {
+ CHECK_CALL(netplan_state_finish_ovs_write(np_state, rootdir, &error)); // OVS cleanup unit is always written
+ if (np_state->netdefs) {
g_debug("Generating output files..");
- g_list_foreach (netdefs_ordered, nd_iterator_list, rootdir);
- write_nm_conf_finish(rootdir);
+ for (GList* iterator = np_state->netdefs_ordered; iterator; iterator = iterator->next) {
+ NetplanNetDefinition* def = (NetplanNetDefinition*) iterator->data;
+ gboolean has_been_written = FALSE;
+ CHECK_CALL(netplan_netdef_write_networkd(np_state, def, rootdir, &has_been_written, &error));
+ any_networkd = any_networkd || has_been_written;
+
+ CHECK_CALL(netplan_netdef_write_ovs(np_state, def, rootdir, &has_been_written, &error));
+ CHECK_CALL(netplan_netdef_write_nm(np_state, def, rootdir, &has_been_written, &error));
+
+ if (def->sriov_explicit_vf_count < G_MAXUINT || def->sriov_link)
+ any_sriov = TRUE;
+ }
+
+ CHECK_CALL(netplan_state_finish_nm_write(np_state, rootdir, &error));
if (any_sriov) write_sriov_conf_finish(rootdir);
/* We may have written .rules & .link files, thus we must
* invalidate udevd cache of its config as by default it only
@@ -282,7 +292,7 @@ int main(int argc, char** argv)
/* Disable /usr/lib/NetworkManager/conf.d/10-globally-managed-devices.conf
* (which restricts NM to wifi and wwan) if global renderer is NM */
- if (netplan_get_global_backend() == NETPLAN_BACKEND_NM)
+ if (netplan_state_get_backend(np_state) == NETPLAN_BACKEND_NM)
g_string_free_to_file(g_string_new(NULL), rootdir, "/run/NetworkManager/conf.d/10-globally-managed-devices.conf", NULL);
if (called_as_generator) {
@@ -324,5 +334,10 @@ int main(int argc, char** argv)
// LCOV_EXCL_STOP
}
- return 0;
+cleanup:
+ if (npp)
+ netplan_parser_clear(&npp);
+ if (np_state)
+ netplan_state_clear(&np_state);
+ return error_code;
}
diff --git a/src/netplan.c b/src/netplan.c
index 6285aa2..6dbf1d8 100644
--- a/src/netplan.c
+++ b/src/netplan.c
@@ -20,7 +20,6 @@
#include "netplan.h"
#include "parse.h"
-#include "parse-globals.h"
#include "yaml-helpers.h"
#include "names.h"
@@ -36,7 +35,7 @@ write_match(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNetDefini
YAML_STRING(event, emitter, "driver", def->match.driver)
YAML_MAPPING_CLOSE(event, emitter);
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -56,7 +55,7 @@ write_auth(yaml_event_t* event, yaml_emitter_t* emitter, NetplanAuthenticationSe
YAML_STRING(event, emitter, "password", auth.password);
YAML_MAPPING_CLOSE(event, emitter);
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -118,7 +117,7 @@ write_bond_params(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNet
YAML_MAPPING_CLOSE(event, emitter);
}
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -173,7 +172,7 @@ write_bridge_params(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanN
YAML_MAPPING_CLOSE(event, emitter);
}
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -192,7 +191,7 @@ write_modem_params(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNe
YAML_STRING(event, emitter, "password", def->modem_params.password);
YAML_STRING(event, emitter, "number", def->modem_params.number);
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
typedef struct {
@@ -206,7 +205,7 @@ _passthrough_handler(GQuark key_id, gpointer value, gpointer user_data)
_passthrough_handler_data *d = user_data;
const gchar* key = g_quark_to_string(key_id);
YAML_STRING(d->event, d->emitter, key, value);
-error: return; // LCOV_EXCL_LINE
+err_path: return; // LCOV_EXCL_LINE
}
static gboolean
@@ -228,7 +227,7 @@ write_backend_settings(yaml_event_t* event, yaml_emitter_t* emitter, NetplanBack
YAML_MAPPING_CLOSE(event, emitter);
}
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -258,12 +257,12 @@ write_access_points(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanN
write_auth(event, emitter, ap->auth);
if (ap->mode != NETPLAN_WIFI_MODE_INFRASTRUCTURE)
YAML_STRING(event, emitter, "mode", netplan_wifi_mode_name(ap->mode));
- if (!write_backend_settings(event, emitter, ap->backend_settings)) goto error;
+ if (!write_backend_settings(event, emitter, ap->backend_settings)) goto err_path;
YAML_MAPPING_CLOSE(event, emitter);
}
YAML_MAPPING_CLOSE(event, emitter);
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -294,7 +293,7 @@ write_addresses(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNetDe
YAML_SEQUENCE_CLOSE(event, emitter);
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -326,7 +325,7 @@ write_nameservers(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNet
}
YAML_MAPPING_CLOSE(event, emitter);
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -364,7 +363,7 @@ write_dhcp_overrides(yaml_event_t* event, yaml_emitter_t* emitter, const char* k
YAML_MAPPING_CLOSE(event, emitter);
}
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -426,7 +425,7 @@ write_tunnel_settings(yaml_event_t* event, yaml_emitter_t* emitter, const Netpla
YAML_SEQUENCE_CLOSE(event, emitter);
}
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -489,7 +488,7 @@ write_routes(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNetDefin
}
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
static gboolean
@@ -593,11 +592,15 @@ write_openvswitch(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanOVS
}
return TRUE;
-error: return FALSE; // LCOV_EXCL_LINE
+err_path: return FALSE; // LCOV_EXCL_LINE
}
-void
-_serialize_yaml(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNetDefinition* def)
+static void
+_serialize_yaml(
+ const NetplanState* np_state,
+ yaml_event_t* event,
+ yaml_emitter_t* emitter,
+ const NetplanNetDefinition* def)
{
GArray* tmp_arr = NULL;
GHashTableIter iter;
@@ -680,7 +683,7 @@ _serialize_yaml(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNetDe
/* Search interfaces */
if (def->type == NETPLAN_DEF_TYPE_BRIDGE || def->type == NETPLAN_DEF_TYPE_BOND) {
tmp_arr = g_array_new(FALSE, FALSE, sizeof(NetplanNetDefinition*));
- g_hash_table_iter_init(&iter, netdefs);
+ g_hash_table_iter_init(&iter, np_state->netdefs);
while (g_hash_table_iter_next (&iter, &key, &value)) {
NetplanNetDefinition *nd = (NetplanNetDefinition *) value;
if (g_strcmp0(nd->bond, def->id) == 0 || g_strcmp0(nd->bridge, def->id) == 0)
@@ -800,18 +803,18 @@ _serialize_yaml(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNetDe
write_modem_params(event, emitter, def);
if (def->type == NETPLAN_DEF_TYPE_WIFI)
- if (!write_access_points(event, emitter, def)) goto error;
+ if (!write_access_points(event, emitter, def)) goto err_path;
/* Handle devices in full fallback/passthrough mode (i.e. 'nm-devices') */
only_passthrough:
- if (!write_backend_settings(event, emitter, def->backend_settings)) goto error;
+ if (!write_backend_settings(event, emitter, def->backend_settings)) goto err_path;
/* Close remaining mappings */
YAML_MAPPING_CLOSE(event, emitter);
return;
// LCOV_EXCL_START
-error:
+err_path:
g_warning("Error generating YAML: %s", emitter->problem);
return;
// LCOV_EXCL_STOP
@@ -819,22 +822,27 @@ error:
/**
* Generate the Netplan YAML configuration for the selected netdef
+ * @np_state: NetplanState (as pointer), the global state to which the netdef belongs
* @def: NetplanNetDefinition (as pointer), the data to be serialized
* @rootdir: If not %NULL, generate configuration in this root directory
* (useful for testing).
*/
-void
-write_netplan_conf(const NetplanNetDefinition* def, const char* rootdir)
+gboolean
+netplan_netdef_write_yaml(
+ const NetplanState* np_state,
+ const NetplanNetDefinition* netdef,
+ const char* rootdir,
+ GError** error)
{
g_autofree gchar *filename = NULL;
g_autofree gchar *path = NULL;
/* NetworkManager produces one file per connection profile
* It's 90-* to be higher priority than the default 70-netplan-set.yaml */
- if (def->backend_settings.nm.uuid)
- filename = g_strconcat("90-NM-", def->backend_settings.nm.uuid, ".yaml", NULL);
+ if (netdef->backend_settings.nm.uuid)
+ filename = g_strconcat("90-NM-", netdef->backend_settings.nm.uuid, ".yaml", NULL);
else
- filename = g_strconcat("10-netplan-", def->id, ".yaml", NULL);
+ filename = g_strconcat("10-netplan-", netdef->id, ".yaml", NULL);
path = g_build_path(G_DIR_SEPARATOR_S, rootdir ?: G_DIR_SEPARATOR_S, "etc", "netplan", filename, NULL);
/* Start rendering YAML output */
@@ -850,10 +858,10 @@ write_netplan_conf(const NetplanNetDefinition* def, const char* rootdir)
YAML_MAPPING_OPEN(event, emitter);
YAML_STRING_PLAIN(event, emitter, "version", "2");
- if (netplan_def_type_name(def->type)) {
- YAML_SCALAR_PLAIN(event, emitter, netplan_def_type_name(def->type));
+ if (netplan_def_type_name(netdef->type)) {
+ YAML_SCALAR_PLAIN(event, emitter, netplan_def_type_name(netdef->type));
YAML_MAPPING_OPEN(event, emitter);
- _serialize_yaml(event, emitter, def);
+ _serialize_yaml(np_state, event, emitter, netdef);
YAML_MAPPING_CLOSE(event, emitter);
}
@@ -863,17 +871,18 @@ write_netplan_conf(const NetplanNetDefinition* def, const char* rootdir)
/* Tear down the YAML emitter */
YAML_OUT_STOP(event, emitter);
fclose(output);
- return;
+ return TRUE;
// LCOV_EXCL_START
-error:
- g_warning("Error generating YAML: %s", emitter->problem);
+err_path:
+ g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Error generating YAML: %s", emitter->problem);
yaml_emitter_delete(emitter);
fclose(output);
+ return FALSE;
// LCOV_EXCL_STOP
}
-gboolean
+static gboolean
contains_netdef_type(gpointer key, gpointer value, gpointer user_data)
{
NetplanNetDefinition *nd = value;
@@ -882,96 +891,99 @@ contains_netdef_type(gpointer key, gpointer value, gpointer user_data)
}
/**
- * Generate the Netplan YAML configuration for all currently parsed netdefs
+ * Generate the Netplan YAML configuration for all netdefs in the state
+ * @np_state: the state for which to generate the config
* @file_hint: Name hint for the generated output YAML file
* @rootdir: If not %NULL, generate configuration in this root directory
* (useful for testing).
*/
-NETPLAN_INTERNAL void
-write_netplan_conf_full(const char* file_hint, const char* rootdir)
+NETPLAN_INTERNAL gboolean
+netplan_state_write_yaml(const NetplanState* np_state, const char* file_hint, const char* rootdir, GError** error)
{
g_autofree gchar *path = NULL;
GHashTable *ovs_ports = NULL;
GHashTableIter iter;
gpointer key, value;
- gboolean global_values = ( (netplan_get_global_backend() != NETPLAN_BACKEND_NONE)
- || has_openvswitch(&ovs_settings_global, NETPLAN_BACKEND_NONE, NULL));
+ gboolean global_values = (np_state->backend != NETPLAN_BACKEND_NONE
+ || has_openvswitch(&np_state->ovs_settings, NETPLAN_BACKEND_NONE, NULL));
- if (global_values || (netdefs && g_hash_table_size(netdefs) > 0)) {
- path = g_build_path(G_DIR_SEPARATOR_S, rootdir ?: G_DIR_SEPARATOR_S, "etc", "netplan", file_hint, NULL);
+ if (!global_values && netplan_state_get_netdefs_size(np_state) == 0) {
+ g_debug("No data/netdefs to serialize into YAML.");
+ return TRUE;
+ }
- /* Start rendering YAML output */
- yaml_emitter_t emitter_data;
- yaml_event_t event_data;
- yaml_emitter_t* emitter = &emitter_data;
- yaml_event_t* event = &event_data;
- FILE *output = fopen(path, "wb");
+ path = g_build_path(G_DIR_SEPARATOR_S, rootdir ?: G_DIR_SEPARATOR_S, "etc", "netplan", file_hint, NULL);
- YAML_OUT_START(event, emitter, output);
- /* build the netplan boilerplate YAML structure */
- YAML_SCALAR_PLAIN(event, emitter, "network");
- YAML_MAPPING_OPEN(event, emitter);
- /* We support version 2 only, currently */
- YAML_STRING_PLAIN(event, emitter, "version", "2");
+ /* Start rendering YAML output */
+ yaml_emitter_t emitter_data;
+ yaml_event_t event_data;
+ yaml_emitter_t* emitter = &emitter_data;
+ yaml_event_t* event = &event_data;
+ FILE *output = fopen(path, "wb");
- if (netplan_get_global_backend() == NETPLAN_BACKEND_NM) {
- YAML_STRING_PLAIN(event, emitter, "renderer", "NetworkManager");
- } else if (netplan_get_global_backend() == NETPLAN_BACKEND_NETWORKD) {
- YAML_STRING_PLAIN(event, emitter, "renderer", "networkd");
- }
+ YAML_OUT_START(event, emitter, output);
+ /* build the netplan boilerplate YAML structure */
+ YAML_SCALAR_PLAIN(event, emitter, "network");
+ YAML_MAPPING_OPEN(event, emitter);
+ /* We support version 2 only, currently */
+ YAML_STRING_PLAIN(event, emitter, "version", "2");
- /* Go through the netdefs type-by-type */
- if (netdefs && g_hash_table_size(netdefs) > 0) {
- for (unsigned i = 0; i < NETPLAN_DEF_TYPE_MAX_; ++i) {
- /* Per-netdef config */
- if (g_hash_table_find(netdefs, contains_netdef_type, &i)) {
- if (netplan_def_type_name(i)) {
- YAML_SCALAR_PLAIN(event, emitter, netplan_def_type_name(i));
- YAML_MAPPING_OPEN(event, emitter);
- g_hash_table_iter_init(&iter, netdefs);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- NetplanNetDefinition *def = (NetplanNetDefinition *) value;
- if (def->type == i)
- _serialize_yaml(event, emitter, def);
- }
- YAML_MAPPING_CLOSE(event, emitter);
- } else if (i == NETPLAN_DEF_TYPE_PORT) {
- g_hash_table_iter_init(&iter, netdefs);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- NetplanNetDefinition *def = (NetplanNetDefinition *) value;
- if (def->type == i) {
- if (!ovs_ports)
- ovs_ports = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- /* Insert each port:peer combination only once */
- if (!g_hash_table_lookup(ovs_ports, def->id))
- g_hash_table_insert(ovs_ports, g_strdup(def->peer), g_strdup(def->id));
- }
+ if (netplan_state_get_backend(np_state) == NETPLAN_BACKEND_NM) {
+ YAML_STRING_PLAIN(event, emitter, "renderer", "NetworkManager");
+ } else if (netplan_state_get_backend(np_state) == NETPLAN_BACKEND_NETWORKD) {
+ YAML_STRING_PLAIN(event, emitter, "renderer", "networkd");
+ }
+
+ /* Go through the netdefs type-by-type */
+ if (netplan_state_get_netdefs_size(np_state) > 0) {
+ for (unsigned i = 0; i < NETPLAN_DEF_TYPE_MAX_; ++i) {
+ /* Per-netdef config */
+ if (g_hash_table_find(np_state->netdefs, contains_netdef_type, &i)) {
+ if (netplan_def_type_name(i)) {
+ YAML_SCALAR_PLAIN(event, emitter, netplan_def_type_name(i));
+ YAML_MAPPING_OPEN(event, emitter);
+ g_hash_table_iter_init(&iter, np_state->netdefs);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ NetplanNetDefinition *def = (NetplanNetDefinition *) value;
+ if (def->type == i)
+ _serialize_yaml(np_state, event, emitter, def);
+ }
+ YAML_MAPPING_CLOSE(event, emitter);
+ } else if (i == NETPLAN_DEF_TYPE_PORT) {
+ g_hash_table_iter_init(&iter, np_state->netdefs);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ NetplanNetDefinition *def = (NetplanNetDefinition *) value;
+ if (def->type == i) {
+ if (!ovs_ports)
+ ovs_ports = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ /* Insert each port:peer combination only once */
+ if (!g_hash_table_lookup(ovs_ports, def->id))
+ g_hash_table_insert(ovs_ports, g_strdup(def->peer), g_strdup(def->id));
}
}
}
}
}
+ }
- write_openvswitch(event, emitter, &ovs_settings_global, NETPLAN_BACKEND_NONE, ovs_ports);
+ write_openvswitch(event, emitter, &np_state->ovs_settings, NETPLAN_BACKEND_NONE, ovs_ports);
- /* Close remaining mappings */
- YAML_MAPPING_CLOSE(event, emitter);
+ /* Close remaining mappings */
+ YAML_MAPPING_CLOSE(event, emitter);
- /* Tear down the YAML emitter */
- YAML_OUT_STOP(event, emitter);
- fclose(output);
- return;
-
- // LCOV_EXCL_START
-error:
- g_warning("Error generating YAML: %s", emitter->problem);
- yaml_emitter_delete(emitter);
- fclose(output);
- // LCOV_EXCL_STOP
- } else {
- g_debug("No data/netdefs to serialize into YAML.");
- }
+ /* Tear down the YAML emitter */
+ YAML_OUT_STOP(event, emitter);
+ fclose(output);
+ return TRUE;
+
+ // LCOV_EXCL_START
+err_path:
+ g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Error generating YAML: %s", emitter->problem);
+ yaml_emitter_delete(emitter);
+ fclose(output);
+ return FALSE;
+ // LCOV_EXCL_STOP
}
/* XXX: implement the following functions, once needed:
@@ -979,15 +991,3 @@ void write_netplan_conf_finish(const char* rootdir)
void cleanup_netplan_conf(const char* rootdir)
*/
-/**
- * Helper function for testing only
- */
-NETPLAN_INTERNAL void
-_write_netplan_conf(const char* netdef_id, const char* rootdir)
-{
- GHashTable* ht = NULL;
- const NetplanNetDefinition* def = NULL;
- ht = netplan_finish_parse(NULL);
- def = g_hash_table_lookup(ht, netdef_id);
- write_netplan_conf(def, rootdir);
-}
diff --git a/src/networkd.c b/src/networkd.c
index a1bc504..55c3d36 100644
--- a/src/networkd.c
+++ b/src/networkd.c
@@ -1149,7 +1149,8 @@ netplan_netdef_write_networkd(
if (def->type >= NETPLAN_DEF_TYPE_VIRTUAL)
write_netdev_file(def, rootdir, path_base);
- write_network_file(def, rootdir, path_base);
+ if (!netplan_netdef_write_network_file(np_state, def, rootdir, path_base, has_been_written, error))
+ return FALSE;
SET_OPT_OUT_PTR(has_been_written, TRUE);
return TRUE;
}
diff --git a/src/parse-globals.h b/src/parse-globals.h
index b72e0aa..e8d802f 100644
--- a/src/parse-globals.h
+++ b/src/parse-globals.h
@@ -20,20 +20,6 @@
#include <glib.h>
#include "types.h"
-/* file that is currently being processed, for useful error messages */
-extern const char*
-current_file;
-
-/* List of "seen" ids not found in netdefs yet by the parser.
- * These are removed when it exists in this list and we reach the point of
- * creating a netdef for that id; so by the time we're done parsing the yaml
- * document it should be empty. */
-extern GHashTable*
-missing_id;
-
-extern int
-missing_ids_found;
-
/* Written/updated by parse_yaml(): char* id → net_definition.
*
* Since both netdefs and netdefs_ordered store pointers to the same elements,
@@ -49,5 +35,9 @@ netdefs_ordered;
extern NetplanOVSSettings
ovs_settings_global;
+
extern NetplanBackend
global_backend;
+
+extern NetplanParser
+global_parser;
diff --git a/src/parse-nm.c b/src/parse-nm.c
index 217eb54..1dc223b 100644
--- a/src/parse-nm.c
+++ b/src/parse-nm.c
@@ -23,6 +23,7 @@
#include "parse-nm.h"
#include "parse.h"
#include "util.h"
+#include "types.h"
#include "util-internal.h"
/**
@@ -429,7 +430,7 @@ read_passthrough(GKeyFile* kf, GData** list)
* @filename: full path to the NetworkManager keyfile
*/
gboolean
-netplan_parse_keyfile(const char* filename, GError** error)
+netplan_parser_load_keyfile(NetplanParser* npp, const char* filename, GError** error)
{
g_autofree gchar *nd_id = NULL;
g_autofree gchar *uuid = NULL;
@@ -479,7 +480,7 @@ netplan_parse_keyfile(const char* filename, GError** error)
} else
nd_id = g_strconcat("NM-", uuid, NULL);
g_free(tmp_str);
- nd = netplan_netdef_new(nd_id, nd_type, NETPLAN_BACKEND_NM);
+ nd = netplan_netdef_new(npp, nd_id, nd_type, NETPLAN_BACKEND_NM);
/* Handle uuid & NM name/id */
nd->backend_settings.nm.uuid = g_strdup(uuid);
diff --git a/src/parse.c b/src/parse.c
index ae8257b..0b2e280 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -28,7 +28,6 @@
#include <yaml.h>
#include "parse.h"
-#include "parse-globals.h"
#include "names.h"
#include "util-internal.h"
#include "error.h"
@@ -54,39 +53,9 @@
dst = g_strdup(src); \
} }
-/* NetplanNetDefinition that is currently being processed */
-static NetplanNetDefinition* cur_netdef;
-
-/* NetplanWifiAccessPoint that is currently being processed */
-static NetplanWifiAccessPoint* cur_access_point;
-
-/* NetplanAuthenticationSettings that are currently being processed */
-static NetplanAuthenticationSettings* cur_auth;
-
-/* NetplanWireguardPeer that is currently being processed */
-static NetplanWireguardPeer* cur_wireguard_peer;
-
-static NetplanAddressOptions* cur_addr_option;
-
-static NetplanIPRoute* cur_route;
-static NetplanIPRule* cur_ip_rule;
-
-/* Filename of the currently parsed YAML file */
-const char* cur_filename;
-
-static NetplanBackend backend_cur_type;
-
extern NetplanState global_state;
-/* Set of IDs in currently parsed YAML file, for being able to detect
- * "duplicate ID within one file" vs. allowing a drop-in to override/amend an
- * existing definition */
-static GHashTable* ids_in_file;
-
-/* Global variables, defined in this file */
-int missing_ids_found;
-const char* current_file;
-GHashTable* missing_id;
+NetplanParser global_parser = {0};
/**
* Load YAML file name into a yaml_document_t.
@@ -100,8 +69,6 @@ load_yaml(const char* yaml, yaml_document_t* doc, GError** error)
yaml_parser_t parser;
gboolean ret = TRUE;
- current_file = yaml;
-
fyaml = g_fopen(yaml, "r");
if (!fyaml) {
g_set_error(error, G_FILE_ERROR, errno, "Cannot open %s: %s", yaml, g_strerror(errno));
@@ -125,7 +92,7 @@ load_yaml(const char* yaml, yaml_document_t* doc, GError** error)
* Raise a GError about a type mismatch and return FALSE.
*/
static gboolean
-assert_type_fn(yaml_node_t* node, yaml_node_type_t expected_type, GError** error)
+assert_type_fn(const NetplanParser* npp, yaml_node_t* node, yaml_node_type_t expected_type, GError** error)
{
if (node->type == expected_type)
return TRUE;
@@ -136,13 +103,13 @@ assert_type_fn(yaml_node_t* node, yaml_node_type_t expected_type, GError** error
return TRUE;
break;
case YAML_SCALAR_NODE:
- yaml_error(node, error, "expected scalar");
+ yaml_error(npp, node, error, "expected scalar");
break;
case YAML_SEQUENCE_NODE:
- yaml_error(node, error, "expected sequence");
+ yaml_error(npp, node, error, "expected sequence");
break;
case YAML_MAPPING_NODE:
- yaml_error(node, error, "expected mapping (check indentation)");
+ yaml_error(npp, node, error, "expected mapping (check indentation)");
break;
// LCOV_EXCL_START
@@ -153,7 +120,7 @@ assert_type_fn(yaml_node_t* node, yaml_node_type_t expected_type, GError** error
return FALSE;
}
-#define assert_type(n,t) { if (!assert_type_fn(n,t,error)) return FALSE; }
+#define assert_type(ctx,n,t) { if (!assert_type_fn(ctx,n,t,error)) return FALSE; }
static inline const char*
scalar(const yaml_node_t* node)
@@ -162,7 +129,7 @@ scalar(const yaml_node_t* node)
}
static void
-add_missing_node(const yaml_node_t* node)
+add_missing_node(NetplanParser *npp, const yaml_node_t* node)
{
NetplanMissingNode* missing;
@@ -171,23 +138,23 @@ add_missing_node(const yaml_node_t* node)
* seen by the compiler). We can use it later to write an sensible error
* message and point the user in the right direction. */
missing = g_new0(NetplanMissingNode, 1);
- missing->netdef_id = cur_netdef->id;
+ missing->netdef_id = npp->current.netdef->id;
missing->node = node;
g_debug("recording missing yaml_node_t %s", scalar(node));
- g_hash_table_insert(missing_id, (gpointer)scalar(node), missing);
+ g_hash_table_insert(npp->missing_id, (gpointer)scalar(node), missing);
}
/**
* Check that node contains a valid ID/interface name. Raise GError if not.
*/
static gboolean
-assert_valid_id(yaml_node_t* node, GError** error)
+assert_valid_id(const NetplanParser* npp, yaml_node_t* node, GError** error)
{
static regex_t re;
static gboolean re_inited = FALSE;
- assert_type(node, YAML_SCALAR_NODE);
+ assert_type(npp, node, YAML_SCALAR_NODE);
if (!re_inited) {
g_assert(regcomp(&re, "^[[:alnum:][:punct:]]+$", REG_EXTENDED|REG_NOSUB) == 0);
@@ -195,28 +162,22 @@ assert_valid_id(yaml_node_t* node, GError** error)
}
if (regexec(&re, scalar(node), 0, NULL, 0) != 0)
- return yaml_error(node, error, "Invalid name '%s'", scalar(node));
+ return yaml_error(npp, node, error, "Invalid name '%s'", scalar(node));
return TRUE;
}
NetplanNetDefinition*
-netplan_netdef_new(const char* id, NetplanDefType type, NetplanBackend backend)
+netplan_netdef_new(NetplanParser *npp, const char* id, NetplanDefType type, NetplanBackend backend)
{
/* create new network definition */
NetplanNetDefinition *netdef = g_new0(NetplanNetDefinition, 1);
reset_netdef(netdef, type, backend);
netdef->id = g_strdup(id);
- if (!netdefs)
- netdefs = g_hash_table_new(g_str_hash, g_str_equal);
- g_hash_table_insert(netdefs, netdef->id, netdef);
- /* netdefs_ordered now owns the allocated object */
- netdefs_ordered = g_list_append(netdefs_ordered, netdef);
-
- /* Update the convenience pointer cur_netdef. This is a weak ref,
- * the previous value is owned by netdefs_ordered */
- cur_netdef = netdef;
-
+ if (!npp->parsed_defs)
+ npp->parsed_defs = g_hash_table_new(g_str_hash, g_str_equal);
+ g_hash_table_insert(npp->parsed_defs, netdef->id, netdef);
+ npp->ordered = g_list_append(npp->ordered, netdef);
return netdef;
}
@@ -224,7 +185,7 @@ netplan_netdef_new(const char* id, NetplanDefType type, NetplanBackend backend)
* Data types and functions for interpreting YAML nodes
****************************************************/
-typedef gboolean (*node_handler) (yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error);
+typedef gboolean (*node_handler) (NetplanParser* npp, yaml_node_t* node, const void* data, GError** error);
typedef struct mapping_entry_handler_s {
/* mapping key (must be scalar) */
@@ -263,11 +224,11 @@ get_handler(const mapping_entry_handler* handlers, const char* key)
* Returns: TRUE on success, FALSE on error (@error gets set then).
*/
static gboolean
-process_mapping(yaml_document_t* doc, yaml_node_t* node, const mapping_entry_handler* handlers, GList** out_values, GError** error)
+process_mapping(NetplanParser* npp, yaml_node_t* node, const mapping_entry_handler* handlers, GList** out_values, GError** error)
{
yaml_node_pair_t* entry;
- assert_type(node, YAML_MAPPING_NODE);
+ assert_type(npp, node, YAML_MAPPING_NODE);
for (entry = node->data.mapping.pairs.start; entry < node->data.mapping.pairs.top; entry++) {
yaml_node_t* key, *value;
@@ -275,22 +236,22 @@ process_mapping(yaml_document_t* doc, yaml_node_t* node, const mapping_entry_han
g_assert(error == NULL || *error == NULL);
- key = yaml_document_get_node(doc, entry->key);
- value = yaml_document_get_node(doc, entry->value);
- assert_type(key, YAML_SCALAR_NODE);
+ key = yaml_document_get_node(&npp->doc, entry->key);
+ value = yaml_document_get_node(&npp->doc, entry->value);
+ assert_type(npp, key, YAML_SCALAR_NODE);
h = get_handler(handlers, scalar(key));
if (!h)
- return yaml_error(key, error, "unknown key '%s'", scalar(key));
- assert_type(value, h->type);
+ return yaml_error(npp, key, error, "unknown key '%s'", scalar(key));
+ assert_type(npp, value, h->type);
if (out_values)
*out_values = g_list_prepend(*out_values, g_strdup(scalar(key)));
if (h->map_handlers) {
g_assert(h->handler == NULL);
g_assert(h->type == YAML_MAPPING_NODE);
- if (!process_mapping(doc, value, h->map_handlers, NULL, error))
+ if (!process_mapping(npp, value, h->map_handlers, NULL, error))
return FALSE;
} else {
- if (!h->handler(doc, value, h->data, error))
+ if (!h->handler(npp, value, h->data, error))
return FALSE;
}
}
@@ -308,7 +269,7 @@ process_mapping(yaml_document_t* doc, yaml_node_t* node, const mapping_entry_han
* @data: offset into entryptr struct where the guint field to write is located
*/
static gboolean
-handle_generic_guint(yaml_document_t* doc, yaml_node_t* node, const void* entryptr, const void* data, GError** error)
+handle_generic_guint(NetplanParser* npp, yaml_node_t* node, const void* entryptr, const void* data, GError** error)
{
g_assert(entryptr);
guint offset = GPOINTER_TO_UINT(data);
@@ -317,7 +278,7 @@ handle_generic_guint(yaml_document_t* doc, yaml_node_t* node, const void* entryp
v = g_ascii_strtoull(scalar(node), &endptr, 10);
if (*endptr != '\0' || v > G_MAXUINT)
- return yaml_error(node, error, "invalid unsigned int value '%s'", scalar(node));
+ return yaml_error(npp, node, error, "invalid unsigned int value '%s'", scalar(node));
*((guint*) ((void*) entryptr + offset)) = (guint) v;
return TRUE;
@@ -330,7 +291,7 @@ handle_generic_guint(yaml_document_t* doc, yaml_node_t* node, const void* entryp
* located
*/
static gboolean
-handle_generic_str(yaml_document_t* doc, yaml_node_t* node, void* entryptr, const void* data, GError** error)
+handle_generic_str(NetplanParser* npp, yaml_node_t* node, void* entryptr, const void* data, GError** error)
{
g_assert(entryptr);
guint offset = GPOINTER_TO_UINT(data);
@@ -347,7 +308,7 @@ handle_generic_str(yaml_document_t* doc, yaml_node_t* node, void* entryptr, cons
* located
*/
static gboolean
-handle_generic_mac(yaml_document_t* doc, yaml_node_t* node, void* entryptr, const void* data, GError** error)
+handle_generic_mac(NetplanParser* npp, yaml_node_t* node, void* entryptr, const void* data, GError** error)
{
g_assert(entryptr);
static regex_t re;
@@ -361,9 +322,9 @@ handle_generic_mac(yaml_document_t* doc, yaml_node_t* node, void* entryptr, cons
}
if (regexec(&re, scalar(node), 0, NULL, 0) != 0)
- return yaml_error(node, error, "Invalid MAC address '%s', must be XX:XX:XX:XX:XX:XX", scalar(node));
+ return yaml_error(npp, node, error, "Invalid MAC address '%s', must be XX:XX:XX:XX:XX:XX", scalar(node));
- return handle_generic_str(doc, node, entryptr, data, error);
+ return handle_generic_str(npp, node, entryptr, data, error);
}
/*
@@ -372,7 +333,7 @@ handle_generic_mac(yaml_document_t* doc, yaml_node_t* node, void* entryptr, cons
* @data: offset into entryptr struct where the boolean field to write is located
*/
static gboolean
-handle_generic_bool(yaml_document_t* doc, yaml_node_t* node, void* entryptr, const void* data, GError** error)
+handle_generic_bool(NetplanParser* npp, yaml_node_t* node, void* entryptr, const void* data, GError** error)
{
g_assert(entryptr);
guint offset = GPOINTER_TO_UINT(data);
@@ -389,7 +350,7 @@ handle_generic_bool(yaml_document_t* doc, yaml_node_t* node, void* entryptr, con
g_ascii_strcasecmp(scalar(node), "n") == 0)
v = FALSE;
else
- return yaml_error(node, error, "invalid boolean value '%s'", scalar(node));
+ return yaml_error(npp, node, error, "invalid boolean value '%s'", scalar(node));
*((gboolean*) ((void*) entryptr + offset)) = v;
return TRUE;
@@ -401,7 +362,7 @@ handle_generic_bool(yaml_document_t* doc, yaml_node_t* node, void* entryptr, con
* @data: offset into entryptr struct where the boolean field to write is located
*/
static gboolean
-handle_generic_map(yaml_document_t* doc, yaml_node_t* node, void* entryptr, const void* data, GError** error)
+handle_generic_map(NetplanParser *npp, yaml_node_t* node, void* entryptr, const void* data, GError** error)
{
guint offset = GPOINTER_TO_UINT(data);
GHashTable** map = (GHashTable**) ((void*) entryptr + offset);
@@ -411,15 +372,15 @@ handle_generic_map(yaml_document_t* doc, yaml_node_t* node, void* entryptr, cons
for (yaml_node_pair_t* entry = node->data.mapping.pairs.start; entry < node->data.mapping.pairs.top; entry++) {
yaml_node_t* key, *value;
- key = yaml_document_get_node(doc, entry->key);
- value = yaml_document_get_node(doc, entry->value);
+ key = yaml_document_get_node(&npp->doc, entry->key);
+ value = yaml_document_get_node(&npp->doc, entry->value);
- assert_type(key, YAML_SCALAR_NODE);
- assert_type(value, YAML_SCALAR_NODE);
+ assert_type(npp, key, YAML_SCALAR_NODE);
+ assert_type(npp, value, YAML_SCALAR_NODE);
/* TODO: make sure we free all the memory here */
if (!g_hash_table_insert(*map, g_strdup(scalar(key)), g_strdup(scalar(value))))
- return yaml_error(node, error, "duplicate map entry '%s'", scalar(key));
+ return yaml_error(npp, node, error, "duplicate map entry '%s'", scalar(key));
}
return TRUE;
@@ -431,7 +392,7 @@ handle_generic_map(yaml_document_t* doc, yaml_node_t* node, void* entryptr, cons
* @data: offset into entryptr struct where the boolean field to write is located
*/
static gboolean
-handle_generic_datalist(yaml_document_t* doc, yaml_node_t* node, void* entryptr, const void* data, GError** error)
+handle_generic_datalist(NetplanParser *npp, yaml_node_t* node, void* entryptr, const void* data, GError** error)
{
guint offset = GPOINTER_TO_UINT(data);
GData** list = (GData**) ((void*) entryptr + offset);
@@ -441,11 +402,11 @@ handle_generic_datalist(yaml_document_t* doc, yaml_node_t* node, void* entryptr,
for (yaml_node_pair_t* entry = node->data.mapping.pairs.start; entry < node->data.mapping.pairs.top; entry++) {
yaml_node_t* key, *value;
- key = yaml_document_get_node(doc, entry->key);
- value = yaml_document_get_node(doc, entry->value);
+ key = yaml_document_get_node(&npp->doc, entry->key);
+ value = yaml_document_get_node(&npp->doc, entry->value);
- assert_type(key, YAML_SCALAR_NODE);
- assert_type(value, YAML_SCALAR_NODE);
+ assert_type(npp, key, YAML_SCALAR_NODE);
+ assert_type(npp, value, YAML_SCALAR_NODE);
g_datalist_set_data_full(list, g_strdup(scalar(key)), g_strdup(scalar(value)), g_free);
}
@@ -454,31 +415,31 @@ handle_generic_datalist(yaml_document_t* doc, yaml_node_t* node, void* entryptr,
}
/**
- * Generic handler for setting a cur_netdef string field from a scalar node
+ * 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
* located
*/
static gboolean
-handle_netdef_str(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_str(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_str(doc, node, cur_netdef, data, error);
+ return handle_generic_str(npp, node, npp->current.netdef, data, error);
}
/**
- * Generic handler for setting a cur_netdef ID/iface name field from a scalar node
+ * Generic handler for setting a npp->current.netdef ID/iface name field from a scalar node
* @data: offset into NetplanNetDefinition where the const char* field to write is
* located
*/
static gboolean
-handle_netdef_id(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_id(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (!assert_valid_id(node, error))
+ if (!assert_valid_id(npp, node, error))
return FALSE;
- return handle_netdef_str(doc, node, data, error);
+ return handle_netdef_str(npp, node, data, error);
}
/**
- * Generic handler for setting a cur_netdef ID/iface name field referring to an
+ * Generic handler for setting a npp->current.netdef ID/iface name field referring to an
* existing ID from a scalar node. This handler also includes a special case
* handler for OVS VLANs, switching the backend implicitly to OVS for such
* interfaces
@@ -486,20 +447,21 @@ handle_netdef_id(yaml_document_t* doc, yaml_node_t* node, const void* data, GErr
* located
*/
static gboolean
-handle_netdef_id_ref(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_id_ref(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
guint offset = GPOINTER_TO_UINT(data);
NetplanNetDefinition* ref = NULL;
- ref = g_hash_table_lookup(netdefs, scalar(node));
+ ref = g_hash_table_lookup(npp->parsed_defs, scalar(node));
if (!ref) {
- add_missing_node(node);
+ add_missing_node(npp, node);
} else {
- *((NetplanNetDefinition**) ((void*) cur_netdef + offset)) = ref;
+ NetplanNetDefinition* netdef = npp->current.netdef;
+ *((NetplanNetDefinition**) ((void*) netdef + offset)) = ref;
- if (cur_netdef->type == NETPLAN_DEF_TYPE_VLAN && ref->backend == NETPLAN_BACKEND_OVS) {
- g_debug("%s: VLAN defined for openvswitch interface, choosing OVS backend", cur_netdef->id);
- cur_netdef->backend = NETPLAN_BACKEND_OVS;
+ if (netdef->type == NETPLAN_DEF_TYPE_VLAN && ref->backend == NETPLAN_BACKEND_OVS) {
+ g_debug("%s: VLAN defined for openvswitch interface, choosing OVS backend", netdef->id);
+ netdef->backend = NETPLAN_BACKEND_OVS;
}
}
return TRUE;
@@ -507,41 +469,41 @@ handle_netdef_id_ref(yaml_document_t* doc, yaml_node_t* node, const void* data,
/**
- * Generic handler for setting a cur_netdef MAC address field from a scalar node
+ * Generic handler for setting a npp->current.netdef MAC address field from a scalar node
* @data: offset into NetplanNetDefinition where the const char* field to write is
* located
*/
static gboolean
-handle_netdef_mac(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_mac(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_mac(doc, node, cur_netdef, data, error);
+ return handle_generic_mac(npp, node, npp->current.netdef, data, error);
}
/**
- * Generic handler for setting a cur_netdef gboolean field from a scalar node
+ * Generic handler for setting a npp->current.netdef gboolean field from a scalar node
* @data: offset into NetplanNetDefinition where the gboolean field to write is located
*/
static gboolean
-handle_netdef_bool(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_bool(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_bool(doc, node, cur_netdef, data, error);
+ return handle_generic_bool(npp, node, npp->current.netdef, data, error);
}
/**
- * Generic handler for setting a cur_netdef guint field from a scalar node
+ * Generic handler for setting a npp->current.netdef guint field from a scalar node
* @data: offset into NetplanNetDefinition where the guint field to write is located
*/
static gboolean
-handle_netdef_guint(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_guint(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_guint(doc, node, cur_netdef, data, error);
+ return handle_generic_guint(npp, node, npp->current.netdef, data, error);
}
static gboolean
-handle_netdef_ip4(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_ip4(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
guint offset = GPOINTER_TO_UINT(data);
- char** dest = (char**) ((void*) cur_netdef + offset);
+ char** dest = (char**) ((void*) npp->current.netdef + offset);
g_autofree char* addr = NULL;
char* prefix_len;
@@ -552,12 +514,12 @@ handle_netdef_ip4(yaml_document_t* doc, yaml_node_t* node, const void* data, GEr
/* FIXME: stop excluding this from coverage; refactor address handling instead */
// LCOV_EXCL_START
if (prefix_len)
- return yaml_error(node, error,
+ return yaml_error(npp, node, error,
"invalid address: a single IPv4 address (without /prefixlength) is required");
/* is it an IPv4 address? */
if (!is_ip4_address(addr))
- return yaml_error(node, error,
+ return yaml_error(npp, node, error,
"invalid IPv4 address: %s", scalar(node));
// LCOV_EXCL_STOP
@@ -568,10 +530,10 @@ handle_netdef_ip4(yaml_document_t* doc, yaml_node_t* node, const void* data, GEr
}
static gboolean
-handle_netdef_ip6(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_ip6(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
guint offset = GPOINTER_TO_UINT(data);
- char** dest = (char**) ((void*) cur_netdef + offset);
+ char** dest = (char**) ((void*) npp->current.netdef + offset);
g_autofree char* addr = NULL;
char* prefix_len;
@@ -582,12 +544,12 @@ handle_netdef_ip6(yaml_document_t* doc, yaml_node_t* node, const void* data, GEr
/* FIXME: stop excluding this from coverage; refactor address handling instead */
// LCOV_EXCL_START
if (prefix_len)
- return yaml_error(node, error,
+ return yaml_error(npp, node, error,
"invalid address: a single IPv6 address (without /prefixlength) is required");
/* is it an IPv6 address? */
if (!is_ip6_address(addr))
- return yaml_error(node, error,
+ return yaml_error(npp, node, error,
"invalid IPv6 address: %s", scalar(node));
// LCOV_EXCL_STOP
@@ -598,40 +560,40 @@ handle_netdef_ip6(yaml_document_t* doc, yaml_node_t* node, const void* data, GEr
}
static gboolean
-handle_netdef_addrgen(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_netdef_addrgen(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- g_assert(cur_netdef);
+ g_assert(npp->current.netdef);
if (strcmp(scalar(node), "eui64") == 0)
- cur_netdef->ip6_addr_gen_mode = NETPLAN_ADDRGEN_EUI64;
+ npp->current.netdef->ip6_addr_gen_mode = NETPLAN_ADDRGEN_EUI64;
else if (strcmp(scalar(node), "stable-privacy") == 0)
- cur_netdef->ip6_addr_gen_mode = NETPLAN_ADDRGEN_STABLEPRIVACY;
+ npp->current.netdef->ip6_addr_gen_mode = NETPLAN_ADDRGEN_STABLEPRIVACY;
else
- return yaml_error(node, error, "unknown ipv6-address-generation '%s'", scalar(node));
+ return yaml_error(npp, node, error, "unknown ipv6-address-generation '%s'", scalar(node));
return TRUE;
}
static gboolean
-handle_netdef_addrtok(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_addrtok(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_netdef);
- gboolean ret = handle_netdef_str(doc, node, data, error);
- if (!is_ip6_address(cur_netdef->ip6_addr_gen_token))
- return yaml_error(node, error, "invalid ipv6-address-token '%s'", scalar(node));
+ g_assert(npp->current.netdef);
+ gboolean ret = handle_netdef_str(npp, node, data, error);
+ if (!is_ip6_address(npp->current.netdef->ip6_addr_gen_token))
+ return yaml_error(npp, node, error, "invalid ipv6-address-token '%s'", scalar(node));
return ret;
}
static gboolean
-handle_netdef_map(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_map(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_netdef);
- return handle_generic_map(doc, node, cur_netdef, data, error);
+ g_assert(npp->current.netdef);
+ return handle_generic_map(npp, node, npp->current.netdef, data, error);
}
static gboolean
-handle_netdef_datalist(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_netdef_datalist(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_netdef);
- return handle_generic_datalist(doc, node, cur_netdef, data, error);
+ g_assert(npp->current.netdef);
+ return handle_generic_datalist(npp, node, npp->current.netdef, data, error);
}
/****************************************************
@@ -650,45 +612,47 @@ static const mapping_entry_handler match_handlers[] = {
****************************************************/
static gboolean
-handle_auth_str(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_auth_str(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_auth);
+ g_assert(npp->current.auth);
guint offset = GPOINTER_TO_UINT(data);
- char** dest = (char**) ((void*) cur_auth + offset);
+ char** dest = (char**) ((void*) npp->current.auth + offset);
g_free(*dest);
*dest = g_strdup(scalar(node));
return TRUE;
}
static gboolean
-handle_auth_key_management(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_auth_key_management(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- g_assert(cur_auth);
+ NetplanAuthenticationSettings* auth = npp->current.auth;
+ g_assert(auth);
if (strcmp(scalar(node), "none") == 0)
- cur_auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_NONE;
+ auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_NONE;
else if (strcmp(scalar(node), "psk") == 0)
- cur_auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_WPA_PSK;
+ auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_WPA_PSK;
else if (strcmp(scalar(node), "eap") == 0)
- cur_auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_WPA_EAP;
+ auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_WPA_EAP;
else if (strcmp(scalar(node), "802.1x") == 0)
- cur_auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_8021X;
+ auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_8021X;
else
- return yaml_error(node, error, "unknown key management type '%s'", scalar(node));
+ return yaml_error(npp, node, error, "unknown key management type '%s'", scalar(node));
return TRUE;
}
static gboolean
-handle_auth_method(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_auth_method(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- g_assert(cur_auth);
+ NetplanAuthenticationSettings* auth = npp->current.auth;
+ g_assert(auth);
if (strcmp(scalar(node), "tls") == 0)
- cur_auth->eap_method = NETPLAN_AUTH_EAP_TLS;
+ auth->eap_method = NETPLAN_AUTH_EAP_TLS;
else if (strcmp(scalar(node), "peap") == 0)
- cur_auth->eap_method = NETPLAN_AUTH_EAP_PEAP;
+ auth->eap_method = NETPLAN_AUTH_EAP_PEAP;
else if (strcmp(scalar(node), "ttls") == 0)
- cur_auth->eap_method = NETPLAN_AUTH_EAP_TTLS;
+ auth->eap_method = NETPLAN_AUTH_EAP_TTLS;
else
- return yaml_error(node, error, "unknown EAP method '%s'", scalar(node));
+ return yaml_error(npp, node, error, "unknown EAP method '%s'", scalar(node));
return TRUE;
}
@@ -711,11 +675,10 @@ static const mapping_entry_handler auth_handlers[] = {
****************************************************/
static NetplanBackend
-get_default_backend_for_type(NetplanDefType type)
+get_default_backend_for_type(const NetplanParser *npp, NetplanDefType type)
{
- NetplanBackend backend = netplan_state_get_backend(&global_state);
- if (backend != NETPLAN_BACKEND_NONE)
- return backend;
+ if (npp->global_backend != NETPLAN_BACKEND_NONE)
+ return npp->global_backend;
/* networkd can handle all device types at the moment, so nothing
* type-specific */
@@ -723,88 +686,92 @@ get_default_backend_for_type(NetplanDefType type)
}
static gboolean
-handle_access_point_str(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_access_point_str(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_str(doc, node, cur_access_point, data, error);
+ return handle_generic_str(npp, node, npp->current.access_point, data, error);
}
static gboolean
-handle_access_point_datalist(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_access_point_datalist(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_access_point);
- return handle_generic_datalist(doc, node, cur_access_point, data, error);
+ g_assert(npp->current.access_point);
+ return handle_generic_datalist(npp, node, npp->current.access_point, data, error);
}
static gboolean
-handle_access_point_guint(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_access_point_guint(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_guint(doc, node, cur_access_point, data, error);
+ return handle_generic_guint(npp, node, npp->current.access_point, data, error);
}
static gboolean
-handle_access_point_mac(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_access_point_mac(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_mac(doc, node, cur_access_point, data, error);
+ return handle_generic_mac(npp, node, npp->current.access_point, data, error);
}
static gboolean
-handle_access_point_bool(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_access_point_bool(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_bool(doc, node, cur_access_point, data, error);
+ return handle_generic_bool(npp, node, npp->current.access_point, data, error);
}
static gboolean
-handle_access_point_password(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_access_point_password(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- g_assert(cur_access_point);
+ NetplanWifiAccessPoint *access_point = npp->current.access_point;
+ g_assert(access_point);
/* shortcut for WPA-PSK */
- cur_access_point->has_auth = TRUE;
- cur_access_point->auth.key_management = NETPLAN_AUTH_KEY_MANAGEMENT_WPA_PSK;
- g_free(cur_access_point->auth.password);
- cur_access_point->auth.password = g_strdup(scalar(node));
+ access_point->has_auth = TRUE;
+ access_point->auth.key_management = NETPLAN_AUTH_KEY_MANAGEMENT_WPA_PSK;
+ g_free(access_point->auth.password);
+ access_point->auth.password = g_strdup(scalar(node));
return TRUE;
}
static gboolean
-handle_access_point_auth(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_access_point_auth(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
+ NetplanWifiAccessPoint *access_point = npp->current.access_point;
gboolean ret;
- g_assert(cur_access_point);
- cur_access_point->has_auth = TRUE;
+ g_assert(access_point);
+ access_point->has_auth = TRUE;
- cur_auth = &cur_access_point->auth;
- ret = process_mapping(doc, node, auth_handlers, NULL, error);
- cur_auth = NULL;
+ npp->current.auth = &access_point->auth;
+ ret = process_mapping(npp, node, auth_handlers, NULL, error);
+ npp->current.auth = NULL;
return ret;
}
static gboolean
-handle_access_point_mode(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_access_point_mode(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- g_assert(cur_access_point);
+ NetplanWifiAccessPoint *access_point = npp->current.access_point;
+ g_assert(access_point);
if (strcmp(scalar(node), "infrastructure") == 0)
- cur_access_point->mode = NETPLAN_WIFI_MODE_INFRASTRUCTURE;
+ access_point->mode = NETPLAN_WIFI_MODE_INFRASTRUCTURE;
else if (strcmp(scalar(node), "adhoc") == 0)
- cur_access_point->mode = NETPLAN_WIFI_MODE_ADHOC;
+ access_point->mode = NETPLAN_WIFI_MODE_ADHOC;
else if (strcmp(scalar(node), "ap") == 0)
- cur_access_point->mode = NETPLAN_WIFI_MODE_AP;
+ access_point->mode = NETPLAN_WIFI_MODE_AP;
else
- return yaml_error(node, error, "unknown wifi mode '%s'", scalar(node));
+ return yaml_error(npp, node, error, "unknown wifi mode '%s'", scalar(node));
return TRUE;
}
static gboolean
-handle_access_point_band(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_access_point_band(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- g_assert(cur_access_point);
+ NetplanWifiAccessPoint *access_point = npp->current.access_point;
+ g_assert(access_point);
if (strcmp(scalar(node), "5GHz") == 0 || strcmp(scalar(node), "5G") == 0)
- cur_access_point->band = NETPLAN_WIFI_BAND_5;
+ access_point->band = NETPLAN_WIFI_BAND_5;
else if (strcmp(scalar(node), "2.4GHz") == 0 || strcmp(scalar(node), "2.4G") == 0)
- cur_access_point->band = NETPLAN_WIFI_BAND_24;
+ access_point->band = NETPLAN_WIFI_BAND_24;
else
- return yaml_error(node, error, "unknown wifi band '%s'", scalar(node));
+ return yaml_error(npp, node, error, "unknown wifi band '%s'", scalar(node));
return TRUE;
}
@@ -847,55 +814,55 @@ static const mapping_entry_handler wifi_access_point_handlers[] = {
* Parse scalar node's string into a netdef_backend.
*/
static gboolean
-parse_renderer(yaml_node_t* node, NetplanBackend* backend, GError** error)
+parse_renderer(NetplanParser* npp, yaml_node_t* node, NetplanBackend* backend, GError** error)
{
if (strcmp(scalar(node), "networkd") == 0)
*backend = NETPLAN_BACKEND_NETWORKD;
else if (strcmp(scalar(node), "NetworkManager") == 0)
*backend = NETPLAN_BACKEND_NM;
else
- return yaml_error(node, error, "unknown renderer '%s'", scalar(node));
+ return yaml_error(npp, node, error, "unknown renderer '%s'", scalar(node));
return TRUE;
}
static gboolean
-handle_netdef_renderer(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_netdef_renderer(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- if (cur_netdef->type == NETPLAN_DEF_TYPE_VLAN) {
+ if (npp->current.netdef->type == NETPLAN_DEF_TYPE_VLAN) {
if (strcmp(scalar(node), "sriov") == 0) {
- cur_netdef->sriov_vlan_filter = TRUE;
+ npp->current.netdef->sriov_vlan_filter = TRUE;
return TRUE;
}
}
- return parse_renderer(node, &cur_netdef->backend, error);
+ return parse_renderer(npp, node, &npp->current.netdef->backend, error);
}
static gboolean
-handle_accept_ra(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_accept_ra(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- gboolean ret = handle_generic_bool(doc, node, cur_netdef, data, error);
- if (cur_netdef->accept_ra)
- cur_netdef->accept_ra = NETPLAN_RA_MODE_ENABLED;
+ gboolean ret = handle_generic_bool(npp, node, npp->current.netdef, data, error);
+ if (npp->current.netdef->accept_ra)
+ npp->current.netdef->accept_ra = NETPLAN_RA_MODE_ENABLED;
else
- cur_netdef->accept_ra = NETPLAN_RA_MODE_DISABLED;
+ npp->current.netdef->accept_ra = NETPLAN_RA_MODE_DISABLED;
return ret;
}
static gboolean
-handle_activation_mode(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_activation_mode(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
if (g_strcmp0(scalar(node), "manual") && g_strcmp0(scalar(node), "off"))
- return yaml_error(node, error, "Value of 'activation-mode' needs to be 'manual' or 'off'");
+ return yaml_error(npp, node, error, "Value of 'activation-mode' needs to be 'manual' or 'off'");
- return handle_netdef_str(doc, node, data, error);
+ return handle_netdef_str(npp, node, data, error);
}
static gboolean
-handle_match(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_match(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- cur_netdef->has_match = TRUE;
- return process_mapping(doc, node, match_handlers, NULL, error);
+ npp->current.netdef->has_match = TRUE;
+ return process_mapping(npp, node, match_handlers, NULL, error);
}
NETPLAN_ABI struct NetplanWifiWowlanType
@@ -913,56 +880,56 @@ NETPLAN_WIFI_WOWLAN_TYPES[] = {
};
static gboolean
-handle_wowlan(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_wowlan(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
- assert_type(entry, YAML_SCALAR_NODE);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
int found = FALSE;
for (unsigned i = 0; NETPLAN_WIFI_WOWLAN_TYPES[i].name != NULL; ++i) {
if (g_ascii_strcasecmp(scalar(entry), NETPLAN_WIFI_WOWLAN_TYPES[i].name) == 0) {
- cur_netdef->wowlan |= NETPLAN_WIFI_WOWLAN_TYPES[i].flag;
+ npp->current.netdef->wowlan |= NETPLAN_WIFI_WOWLAN_TYPES[i].flag;
found = TRUE;
break;
}
}
if (!found)
- return yaml_error(node, error, "invalid value for wakeonwlan: '%s'", scalar(entry));
+ return yaml_error(npp, node, error, "invalid value for wakeonwlan: '%s'", scalar(entry));
}
- if (cur_netdef->wowlan > NETPLAN_WIFI_WOWLAN_DEFAULT && cur_netdef->wowlan & NETPLAN_WIFI_WOWLAN_TYPES[0].flag)
- return yaml_error(node, error, "'default' is an exclusive flag for wakeonwlan");
+ if (npp->current.netdef->wowlan > NETPLAN_WIFI_WOWLAN_DEFAULT && npp->current.netdef->wowlan & NETPLAN_WIFI_WOWLAN_TYPES[0].flag)
+ return yaml_error(npp, node, error, "'default' is an exclusive flag for wakeonwlan");
return TRUE;
}
static gboolean
-handle_auth(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_auth(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
gboolean ret;
- cur_netdef->has_auth = TRUE;
+ npp->current.netdef->has_auth = TRUE;
- cur_auth = &cur_netdef->auth;
- ret = process_mapping(doc, node, auth_handlers, NULL, error);
- cur_auth = NULL;
+ npp->current.auth = &npp->current.netdef->auth;
+ ret = process_mapping(npp, node, auth_handlers, NULL, error);
+ npp->current.auth = NULL;
return ret;
}
static gboolean
-handle_address_option_lifetime(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_address_option_lifetime(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
if (g_ascii_strcasecmp(scalar(node), "0") != 0 &&
g_ascii_strcasecmp(scalar(node), "forever") != 0) {
- return yaml_error(node, error, "invalid lifetime value '%s'", scalar(node));
+ return yaml_error(npp, node, error, "invalid lifetime value '%s'", scalar(node));
}
- return handle_generic_str(doc, node, cur_addr_option, data, error);
+ return handle_generic_str(npp, node, npp->current.addr_options, data, error);
}
static gboolean
-handle_address_option_label(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_address_option_label(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_str(doc, node, cur_addr_option, data, error);
+ return handle_generic_str(npp, node, npp->current.addr_options, data, error);
}
const mapping_entry_handler address_option_handlers[] = {
@@ -977,7 +944,7 @@ const mapping_entry_handler address_option_handlers[] = {
* @data: offset into entryptr struct where the array to write is located
*/
static gboolean
-handle_generic_addresses(yaml_document_t* doc, yaml_node_t* node, gboolean check_zero_prefix, GArray** ip4, GArray** ip6, GError** error)
+handle_generic_addresses(NetplanParser* npp, yaml_node_t* node, gboolean check_zero_prefix, GArray** ip4, GArray** ip6, GError** error)
{
g_assert(ip4);
g_assert(ip6);
@@ -985,58 +952,60 @@ handle_generic_addresses(yaml_document_t* doc, yaml_node_t* node, gboolean check
g_autofree char* addr = NULL;
char* prefix_len;
guint64 prefix_len_num;
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
yaml_node_t *key = NULL;
yaml_node_t *value = NULL;
if (entry->type != YAML_SCALAR_NODE && entry->type != YAML_MAPPING_NODE) {
- return yaml_error(entry, error, "expected either scalar or mapping (check indentation)");
+ return yaml_error(npp, entry, error, "expected either scalar or mapping (check indentation)");
}
if (entry->type == YAML_MAPPING_NODE) {
- key = yaml_document_get_node(doc, entry->data.mapping.pairs.start->key);
- value = yaml_document_get_node(doc, entry->data.mapping.pairs.start->value);
+ key = yaml_document_get_node(&npp->doc, entry->data.mapping.pairs.start->key);
+ value = yaml_document_get_node(&npp->doc, entry->data.mapping.pairs.start->value);
entry = key;
}
- assert_type(entry, YAML_SCALAR_NODE);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
/* split off /prefix_len */
addr = g_strdup(scalar(entry));
prefix_len = strrchr(addr, '/');
if (!prefix_len)
- return yaml_error(node, error, "address '%s' is missing /prefixlength", scalar(entry));
+ return yaml_error(npp, node, error, "address '%s' is missing /prefixlength", scalar(entry));
*prefix_len = '\0';
prefix_len++; /* skip former '/' into first char of prefix */
prefix_len_num = g_ascii_strtoull(prefix_len, NULL, 10);
if (value) {
if (!is_ip4_address(addr) && !is_ip6_address(addr))
- return yaml_error(node, error, "malformed address '%s', must be X.X.X.X/NN or X:X:X:X:X:X:X:X/NN", scalar(entry));
+ return yaml_error(npp, node, error, "malformed address '%s', must be X.X.X.X/NN or X:X:X:X:X:X:X:X/NN", scalar(entry));
- if (!cur_netdef->address_options)
- cur_netdef->address_options = g_array_new(FALSE, FALSE, sizeof(NetplanAddressOptions*));
+ if (!npp->current.netdef->address_options)
+ npp->current.netdef->address_options = g_array_new(FALSE, FALSE, sizeof(NetplanAddressOptions*));
- for (unsigned i = 0; i < cur_netdef->address_options->len; ++i) {
- NetplanAddressOptions* opts = g_array_index(cur_netdef->address_options, NetplanAddressOptions*, i);
+ for (unsigned i = 0; i < npp->current.netdef->address_options->len; ++i) {
+ NetplanAddressOptions* opts = g_array_index(npp->current.netdef->address_options, NetplanAddressOptions*, i);
/* check for multi-pass parsing, return early if options for this address already exist */
if (!g_strcmp0(scalar(key), opts->address))
return TRUE;
}
- cur_addr_option = g_new0(NetplanAddressOptions, 1);
- cur_addr_option->address = g_strdup(scalar(key));
+ npp->current.addr_options = g_new0(NetplanAddressOptions, 1);
+ npp->current.addr_options->address = g_strdup(scalar(key));
- if (!process_mapping(doc, value, address_option_handlers, NULL, error))
+ if (!process_mapping(npp, value, address_option_handlers, NULL, error))
return FALSE;
- g_array_append_val(cur_netdef->address_options, cur_addr_option);
+ g_array_append_val(npp->current.netdef->address_options, npp->current.addr_options);
+ npp->current.addr_options = NULL;
+
continue;
}
/* is it an IPv4 address? */
if (is_ip4_address(addr)) {
if ((check_zero_prefix && prefix_len_num == 0) || prefix_len_num > 32)
- return yaml_error(node, error, "invalid prefix length in address '%s'", scalar(entry));
+ return yaml_error(npp, node, error, "invalid prefix length in address '%s'", scalar(entry));
if (!*ip4)
*ip4 = g_array_new(FALSE, FALSE, sizeof(char*));
@@ -1054,7 +1023,7 @@ skip_ip4:
/* is it an IPv6 address? */
if (is_ip6_address(addr)) {
if ((check_zero_prefix && prefix_len_num == 0) || prefix_len_num > 128)
- return yaml_error(node, error, "invalid prefix length in address '%s'", scalar(entry));
+ return yaml_error(npp, node, error, "invalid prefix length in address '%s'", scalar(entry));
if (!*ip6)
*ip6 = g_array_new(FALSE, FALSE, sizeof(char*));
@@ -1068,106 +1037,106 @@ skip_ip6:
continue;
}
- return yaml_error(node, error, "malformed address '%s', must be X.X.X.X/NN or X:X:X:X:X:X:X:X/NN", scalar(entry));
+ return yaml_error(npp, node, error, "malformed address '%s', must be X.X.X.X/NN or X:X:X:X:X:X:X:X/NN", scalar(entry));
}
return TRUE;
}
static gboolean
-handle_addresses(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_addresses(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- return handle_generic_addresses(doc, node, TRUE, &(cur_netdef->ip4_addresses), &(cur_netdef->ip6_addresses), error);
+ return handle_generic_addresses(npp, node, TRUE, &(npp->current.netdef->ip4_addresses), &(npp->current.netdef->ip6_addresses), error);
}
static gboolean
-handle_gateway4(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_gateway4(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
if (!is_ip4_address(scalar(node)))
- return yaml_error(node, error, "invalid IPv4 address '%s'", scalar(node));
- set_str_if_null(cur_netdef->gateway4, scalar(node));
+ return yaml_error(npp, node, error, "invalid IPv4 address '%s'", scalar(node));
+ set_str_if_null(npp->current.netdef->gateway4, scalar(node));
g_warning("`gateway4` has been deprecated, use default routes instead.\n"
"See the 'Default routes' section of the documentation for more details.");
return TRUE;
}
static gboolean
-handle_gateway6(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_gateway6(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
if (!is_ip6_address(scalar(node)))
- return yaml_error(node, error, "invalid IPv6 address '%s'", scalar(node));
- set_str_if_null(cur_netdef->gateway6, scalar(node));
+ return yaml_error(npp, node, error, "invalid IPv6 address '%s'", scalar(node));
+ set_str_if_null(npp->current.netdef->gateway6, scalar(node));
g_warning("`gateway6` has been deprecated, use default routes instead.\n"
"See the 'Default routes' section of the documentation for more details.");
return TRUE;
}
static gboolean
-handle_wifi_access_points(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_wifi_access_points(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
for (yaml_node_pair_t* entry = node->data.mapping.pairs.start; entry < node->data.mapping.pairs.top; entry++) {
+ NetplanWifiAccessPoint *access_point = NULL;
yaml_node_t* key, *value;
gboolean ret = TRUE;
- key = yaml_document_get_node(doc, entry->key);
- assert_type(key, YAML_SCALAR_NODE);
- value = yaml_document_get_node(doc, entry->value);
- assert_type(value, YAML_MAPPING_NODE);
+ key = yaml_document_get_node(&npp->doc, entry->key);
+ assert_type(npp, key, YAML_SCALAR_NODE);
+ value = yaml_document_get_node(&npp->doc, entry->value);
+ assert_type(npp, value, YAML_MAPPING_NODE);
- g_assert(cur_access_point == NULL);
- cur_access_point = g_new0(NetplanWifiAccessPoint, 1);
- cur_access_point->ssid = g_strdup(scalar(key));
- g_debug("%s: adding wifi AP '%s'", cur_netdef->id, cur_access_point->ssid);
+ g_assert(access_point == NULL);
+ access_point = g_new0(NetplanWifiAccessPoint, 1);
+ access_point->ssid = g_strdup(scalar(key));
+ g_debug("%s: adding wifi AP '%s'", npp->current.netdef->id, access_point->ssid);
/* Check if there's already an SSID with that name */
- if (cur_netdef->access_points &&
- g_hash_table_lookup(cur_netdef->access_points, cur_access_point->ssid)) {
- ret = yaml_error(key, error, "%s: Duplicate access point SSID '%s'", cur_netdef->id, cur_access_point->ssid);
+ if (npp->current.netdef->access_points &&
+ g_hash_table_lookup(npp->current.netdef->access_points, access_point->ssid)) {
+ ret = yaml_error(npp, key, error, "%s: Duplicate access point SSID '%s'", npp->current.netdef->id, access_point->ssid);
}
- if (!ret || !process_mapping(doc, value, wifi_access_point_handlers, NULL, error)) {
- g_free(cur_access_point->ssid);
- g_free(cur_access_point); /* XXX: should be more in-depth! */
- cur_access_point = NULL;
+ npp->current.access_point = access_point;
+ if (!ret || !process_mapping(npp, value, wifi_access_point_handlers, NULL, error)) {
+ access_point_clear(&npp->current.access_point, npp->current.backend);
return FALSE;
}
- if (!cur_netdef->access_points)
- cur_netdef->access_points = g_hash_table_new(g_str_hash, g_str_equal);
- g_hash_table_insert(cur_netdef->access_points, cur_access_point->ssid, cur_access_point);
- cur_access_point = NULL;
+ if (!npp->current.netdef->access_points)
+ npp->current.netdef->access_points = g_hash_table_new(g_str_hash, g_str_equal);
+ g_hash_table_insert(npp->current.netdef->access_points, access_point->ssid, access_point);
+ npp->current.access_point = NULL;
}
return TRUE;
}
/**
- * Handler for bridge "interfaces:" list. We don't store that list in cur_netdef,
- * but set cur_netdef's ID in all listed interfaces' "bond" or "bridge" field.
+ * Handler for bridge "interfaces:" list. We don't store that list in npp->current.netdef,
+ * but set npp->current.netdef's ID in all listed interfaces' "bond" or "bridge" field.
* @data: ignored
*/
static gboolean
-handle_bridge_interfaces(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_bridge_interfaces(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
/* all entries must refer to already defined IDs */
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
NetplanNetDefinition *component;
- assert_type(entry, YAML_SCALAR_NODE);
- component = g_hash_table_lookup(netdefs, scalar(entry));
+ assert_type(npp, entry, YAML_SCALAR_NODE);
+ component = g_hash_table_lookup(npp->parsed_defs, scalar(entry));
if (!component) {
- add_missing_node(entry);
+ add_missing_node(npp, entry);
} else {
- if (component->bridge && g_strcmp0(component->bridge, cur_netdef->id) != 0)
- return yaml_error(node, error, "%s: interface '%s' is already assigned to bridge %s",
- cur_netdef->id, scalar(entry), component->bridge);
+ if (component->bridge && g_strcmp0(component->bridge, npp->current.netdef->id) != 0)
+ return yaml_error(npp, node, error, "%s: interface '%s' is already assigned to bridge %s",
+ npp->current.netdef->id, scalar(entry), component->bridge);
if (component->bond)
- return yaml_error(node, error, "%s: interface '%s' is already assigned to bond %s",
- cur_netdef->id, scalar(entry), component->bond);
- set_str_if_null(component->bridge, cur_netdef->id);
+ return yaml_error(npp, node, error, "%s: interface '%s' is already assigned to bond %s",
+ npp->current.netdef->id, scalar(entry), component->bond);
+ set_str_if_null(component->bridge, npp->current.netdef->id);
if (component->backend == NETPLAN_BACKEND_OVS) {
- g_debug("%s: Bridge contains openvswitch interface, choosing OVS backend", cur_netdef->id);
- cur_netdef->backend = NETPLAN_BACKEND_OVS;
+ g_debug("%s: Bridge contains openvswitch interface, choosing OVS backend", npp->current.netdef->id);
+ npp->current.netdef->backend = NETPLAN_BACKEND_OVS;
}
}
}
@@ -1181,7 +1150,7 @@ handle_bridge_interfaces(yaml_document_t* doc, yaml_node_t* node, const void* da
* located
*/
static gboolean
-handle_bond_mode(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_bond_mode(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
if (!(strcmp(scalar(node), "balance-rr") == 0 ||
strcmp(scalar(node), "active-backup") == 0 ||
@@ -1192,17 +1161,17 @@ handle_bond_mode(yaml_document_t* doc, yaml_node_t* node, const void* data, GErr
strcmp(scalar(node), "balance-alb") == 0 ||
strcmp(scalar(node), "balance-tcp") == 0 || // only supported for OVS
strcmp(scalar(node), "balance-slb") == 0)) // only supported for OVS
- return yaml_error(node, error, "unknown bond mode '%s'", scalar(node));
+ return yaml_error(npp, node, error, "unknown bond mode '%s'", scalar(node));
/* Implicitly set NETPLAN_BACKEND_OVS if ovs-only mode selected */
if (!strcmp(scalar(node), "balance-tcp") ||
!strcmp(scalar(node), "balance-slb")) {
g_debug("%s: mode '%s' only supported with openvswitch, choosing this backend",
- cur_netdef->id, scalar(node));
- cur_netdef->backend = NETPLAN_BACKEND_OVS;
+ npp->current.netdef->id, scalar(node));
+ npp->current.netdef->backend = NETPLAN_BACKEND_OVS;
}
- return handle_netdef_str(doc, node, data, error);
+ return handle_netdef_str(npp, node, data, error);
}
/**
@@ -1210,28 +1179,28 @@ handle_bond_mode(yaml_document_t* doc, yaml_node_t* node, const void* data, GErr
* @data: ignored
*/
static gboolean
-handle_bond_interfaces(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_bond_interfaces(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
/* all entries must refer to already defined IDs */
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
NetplanNetDefinition *component;
- assert_type(entry, YAML_SCALAR_NODE);
- component = g_hash_table_lookup(netdefs, scalar(entry));
+ assert_type(npp, entry, YAML_SCALAR_NODE);
+ component = g_hash_table_lookup(npp->parsed_defs, scalar(entry));
if (!component) {
- add_missing_node(entry);
+ add_missing_node(npp, entry);
} else {
if (component->bridge)
- return yaml_error(node, error, "%s: interface '%s' is already assigned to bridge %s",
- cur_netdef->id, scalar(entry), component->bridge);
- if (component->bond && g_strcmp0(component->bond, cur_netdef->id) != 0)
- return yaml_error(node, error, "%s: interface '%s' is already assigned to bond %s",
- cur_netdef->id, scalar(entry), component->bond);
- component->bond = g_strdup(cur_netdef->id);
+ return yaml_error(npp, node, error, "%s: interface '%s' is already assigned to bridge %s",
+ npp->current.netdef->id, scalar(entry), component->bridge);
+ if (component->bond && g_strcmp0(component->bond, npp->current.netdef->id) != 0)
+ return yaml_error(npp, node, error, "%s: interface '%s' is already assigned to bond %s",
+ npp->current.netdef->id, scalar(entry), component->bond);
+ component->bond = g_strdup(npp->current.netdef->id);
if (component->backend == NETPLAN_BACKEND_OVS) {
- g_debug("%s: Bond contains openvswitch interface, choosing OVS backend", cur_netdef->id);
- cur_netdef->backend = NETPLAN_BACKEND_OVS;
+ g_debug("%s: Bond contains openvswitch interface, choosing OVS backend", npp->current.netdef->id);
+ npp->current.netdef->backend = NETPLAN_BACKEND_OVS;
}
}
}
@@ -1241,71 +1210,71 @@ handle_bond_interfaces(yaml_document_t* doc, yaml_node_t* node, const void* data
static gboolean
-handle_nameservers_search(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_nameservers_search(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
- assert_type(entry, YAML_SCALAR_NODE);
- if (!cur_netdef->search_domains)
- cur_netdef->search_domains = g_array_new(FALSE, FALSE, sizeof(char*));
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
+ if (!npp->current.netdef->search_domains)
+ npp->current.netdef->search_domains = g_array_new(FALSE, FALSE, sizeof(char*));
char* s = g_strdup(scalar(entry));
- g_array_append_val(cur_netdef->search_domains, s);
+ g_array_append_val(npp->current.netdef->search_domains, s);
}
return TRUE;
}
static gboolean
-handle_nameservers_addresses(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_nameservers_addresses(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
- assert_type(entry, YAML_SCALAR_NODE);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
/* is it an IPv4 address? */
if (is_ip4_address(scalar(entry))) {
- if (!cur_netdef->ip4_nameservers)
- cur_netdef->ip4_nameservers = g_array_new(FALSE, FALSE, sizeof(char*));
+ if (!npp->current.netdef->ip4_nameservers)
+ npp->current.netdef->ip4_nameservers = g_array_new(FALSE, FALSE, sizeof(char*));
char* s = g_strdup(scalar(entry));
- g_array_append_val(cur_netdef->ip4_nameservers, s);
+ g_array_append_val(npp->current.netdef->ip4_nameservers, s);
continue;
}
/* is it an IPv6 address? */
if (is_ip6_address(scalar(entry))) {
- if (!cur_netdef->ip6_nameservers)
- cur_netdef->ip6_nameservers = g_array_new(FALSE, FALSE, sizeof(char*));
+ if (!npp->current.netdef->ip6_nameservers)
+ npp->current.netdef->ip6_nameservers = g_array_new(FALSE, FALSE, sizeof(char*));
char* s = g_strdup(scalar(entry));
- g_array_append_val(cur_netdef->ip6_nameservers, s);
+ g_array_append_val(npp->current.netdef->ip6_nameservers, s);
continue;
}
- return yaml_error(node, error, "malformed address '%s', must be X.X.X.X or X:X:X:X:X:X:X:X", scalar(entry));
+ return yaml_error(npp, node, error, "malformed address '%s', must be X.X.X.X or X:X:X:X:X:X:X:X", scalar(entry));
}
return TRUE;
}
static gboolean
-handle_link_local(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_link_local(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
gboolean ipv4 = FALSE;
gboolean ipv6 = FALSE;
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
- assert_type(entry, YAML_SCALAR_NODE);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
if (g_ascii_strcasecmp(scalar(entry), "ipv4") == 0)
ipv4 = TRUE;
else if (g_ascii_strcasecmp(scalar(entry), "ipv6") == 0)
ipv6 = TRUE;
else
- return yaml_error(node, error, "invalid value for link-local: '%s'", scalar(entry));
+ return yaml_error(npp, node, error, "invalid value for link-local: '%s'", scalar(entry));
}
- cur_netdef->linklocal.ipv4 = ipv4;
- cur_netdef->linklocal.ipv6 = ipv6;
+ npp->current.netdef->linklocal.ipv4 = ipv4;
+ npp->current.netdef->linklocal.ipv6 = ipv6;
return TRUE;
}
@@ -1321,22 +1290,22 @@ NETPLAN_OPTIONAL_ADDRESS_TYPES[] = {
};
static gboolean
-handle_optional_addresses(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_optional_addresses(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
- assert_type(entry, YAML_SCALAR_NODE);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
int found = FALSE;
for (unsigned i = 0; NETPLAN_OPTIONAL_ADDRESS_TYPES[i].name != NULL; ++i) {
if (g_ascii_strcasecmp(scalar(entry), NETPLAN_OPTIONAL_ADDRESS_TYPES[i].name) == 0) {
- cur_netdef->optional_addresses |= NETPLAN_OPTIONAL_ADDRESS_TYPES[i].flag;
+ npp->current.netdef->optional_addresses |= NETPLAN_OPTIONAL_ADDRESS_TYPES[i].flag;
found = TRUE;
break;
}
}
if (!found) {
- return yaml_error(node, error, "invalid value for optional-addresses: '%s'", scalar(entry));
+ return yaml_error(npp, node, error, "invalid value for optional-addresses: '%s'", scalar(entry));
}
}
return TRUE;
@@ -1376,55 +1345,58 @@ check_and_set_family(int family, guint* dest)
/* TODO: (cyphermox) Refactor the functions below. There's a lot of room for reuse. */
static gboolean
-handle_routes_bool(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_routes_bool(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_route);
- return handle_generic_bool(doc, node, cur_route, data, error);
+ g_assert(npp->current.route);
+ return handle_generic_bool(npp, node, npp->current.route, data, error);
}
static gboolean
-handle_routes_scope(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_routes_scope(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (cur_route->scope)
- g_free(cur_route->scope);
- cur_route->scope = g_strdup(scalar(node));
+ NetplanIPRoute* route = npp->current.route;
+ if (route->scope)
+ g_free(route->scope);
+ route->scope = g_strdup(scalar(node));
- if (g_ascii_strcasecmp(cur_route->scope, "global") == 0 ||
- g_ascii_strcasecmp(cur_route->scope, "link") == 0 ||
- g_ascii_strcasecmp(cur_route->scope, "host") == 0)
+ if (g_ascii_strcasecmp(route->scope, "global") == 0 ||
+ g_ascii_strcasecmp(route->scope, "link") == 0 ||
+ g_ascii_strcasecmp(route->scope, "host") == 0)
return TRUE;
- return yaml_error(node, error, "invalid route scope '%s'", cur_route->scope);
+ return yaml_error(npp, node, error, "invalid route scope '%s'", route->scope);
}
static gboolean
-handle_routes_type(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_routes_type(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (cur_route->type)
- g_free(cur_route->type);
- cur_route->type = g_strdup(scalar(node));
+ NetplanIPRoute* route = npp->current.route;
+ if (route->type)
+ g_free(route->type);
+ route->type = g_strdup(scalar(node));
- if (g_ascii_strcasecmp(cur_route->type, "unicast") == 0 ||
- g_ascii_strcasecmp(cur_route->type, "unreachable") == 0 ||
- g_ascii_strcasecmp(cur_route->type, "blackhole") == 0 ||
- g_ascii_strcasecmp(cur_route->type, "prohibit") == 0)
+ if (g_ascii_strcasecmp(route->type, "unicast") == 0 ||
+ g_ascii_strcasecmp(route->type, "unreachable") == 0 ||
+ g_ascii_strcasecmp(route->type, "blackhole") == 0 ||
+ g_ascii_strcasecmp(route->type, "prohibit") == 0)
return TRUE;
- return yaml_error(node, error, "invalid route type '%s'", cur_route->type);
+ return yaml_error(npp, node, error, "invalid route type '%s'", route->type);
}
static gboolean
-handle_routes_ip(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_routes_ip(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
+ NetplanIPRoute* route = npp->current.route;
guint offset = GPOINTER_TO_UINT(data);
int family = get_ip_family(scalar(node));
- char** dest = (char**) ((void*) cur_route + offset);
+ char** dest = (char**) ((void*) route + offset);
if (family < 0)
- return yaml_error(node, error, "invalid IP family '%d'", family);
+ return yaml_error(npp, node, error, "invalid IP family '%d'", family);
- if (!check_and_set_family(family, &cur_route->family))
- return yaml_error(node, error, "IP family mismatch in route to %s", scalar(node));
+ if (!check_and_set_family(family, &route->family))
+ return yaml_error(npp, node, error, "IP family mismatch in route to %s", scalar(node));
g_free(*dest);
*dest = g_strdup(scalar(node));
@@ -1433,27 +1405,28 @@ handle_routes_ip(yaml_document_t* doc, yaml_node_t* node, const void* data, GErr
}
static gboolean
-handle_routes_destination(yaml_document_t *doc, yaml_node_t *node, const void *data, GError **error)
+handle_routes_destination(NetplanParser *npp, yaml_node_t *node, const void *data, GError **error)
{
const char *addr = scalar(node);
if (g_strcmp0(addr, "default") != 0) /* netplan-feature: default-routes */
- return handle_routes_ip(doc, node, route_offset(to), error);
- set_str_if_null(cur_route->to, addr);
+ return handle_routes_ip(npp, node, route_offset(to), error);
+ set_str_if_null(npp->current.route->to, addr);
return TRUE;
}
static gboolean
-handle_ip_rule_ip(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ip_rule_ip(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
+ NetplanIPRule* ip_rule = npp->current.ip_rule;
guint offset = GPOINTER_TO_UINT(data);
int family = get_ip_family(scalar(node));
- char** dest = (char**) ((void*) cur_ip_rule + offset);
+ char** dest = (char**) ((void*) ip_rule + offset);
if (family < 0)
- return yaml_error(node, error, "invalid IP family '%d'", family);
+ return yaml_error(npp, node, error, "invalid IP family '%d'", family);
- if (!check_and_set_family(family, &cur_ip_rule->family))
- return yaml_error(node, error, "IP family mismatch in route to %s", scalar(node));
+ if (!check_and_set_family(family, &ip_rule->family))
+ return yaml_error(npp, node, error, "IP family mismatch in route to %s", scalar(node));
g_free(*dest);
*dest = g_strdup(scalar(node));
@@ -1462,25 +1435,26 @@ handle_ip_rule_ip(yaml_document_t* doc, yaml_node_t* node, const void* data, GEr
}
static gboolean
-handle_ip_rule_guint(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ip_rule_guint(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_ip_rule);
- return handle_generic_guint(doc, node, cur_ip_rule, data, error);
+ g_assert(npp->current.ip_rule);
+ return handle_generic_guint(npp, node, npp->current.ip_rule, data, error);
}
static gboolean
-handle_routes_guint(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_routes_guint(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_route);
- return handle_generic_guint(doc, node, cur_route, data, error);
+ g_assert(npp->current.route);
+ return handle_generic_guint(npp, node, npp->current.route, data, error);
}
static gboolean
-handle_ip_rule_tos(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ip_rule_tos(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- gboolean ret = handle_generic_guint(doc, node, cur_ip_rule, data, error);
- if (cur_ip_rule->tos > 255)
- return yaml_error(node, error, "invalid ToS (must be between 0 and 255): %s", scalar(node));
+ NetplanIPRule* ip_rule = npp->current.ip_rule;
+ gboolean ret = handle_generic_guint(npp, node, ip_rule, data, error);
+ if (ip_rule->tos > 255)
+ return yaml_error(npp, node, error, "invalid ToS (must be between 0 and 255): %s", scalar(node));
return ret;
}
@@ -1489,7 +1463,7 @@ handle_ip_rule_tos(yaml_document_t* doc, yaml_node_t* node, const void* data, GE
****************************************************/
static gboolean
-handle_bridge_path_cost(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_bridge_path_cost(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
for (yaml_node_pair_t* entry = node->data.mapping.pairs.start; entry < node->data.mapping.pairs.top; entry++) {
yaml_node_t* key, *value;
@@ -1498,25 +1472,25 @@ handle_bridge_path_cost(yaml_document_t* doc, yaml_node_t* node, const void* dat
NetplanNetDefinition *component;
guint* ref_ptr;
- key = yaml_document_get_node(doc, entry->key);
- assert_type(key, YAML_SCALAR_NODE);
- value = yaml_document_get_node(doc, entry->value);
- assert_type(value, YAML_SCALAR_NODE);
+ key = yaml_document_get_node(&npp->doc, entry->key);
+ assert_type(npp, key, YAML_SCALAR_NODE);
+ value = yaml_document_get_node(&npp->doc, entry->value);
+ assert_type(npp, value, YAML_SCALAR_NODE);
- component = g_hash_table_lookup(netdefs, scalar(key));
+ component = g_hash_table_lookup(npp->parsed_defs, scalar(key));
if (!component) {
- add_missing_node(key);
+ add_missing_node(npp, key);
} else {
ref_ptr = ((guint*) ((void*) component + GPOINTER_TO_UINT(data)));
if (*ref_ptr)
- return yaml_error(node, error, "%s: interface '%s' already has a path cost of %u",
- cur_netdef->id, scalar(key), *ref_ptr);
+ return yaml_error(npp, node, error, "%s: interface '%s' already has a path cost of %u",
+ npp->current.netdef->id, scalar(key), *ref_ptr);
v = g_ascii_strtoull(scalar(value), &endptr, 10);
if (*endptr != '\0' || v > G_MAXUINT)
- return yaml_error(node, error, "invalid unsigned int value '%s'", scalar(value));
+ return yaml_error(npp, node, error, "invalid unsigned int value '%s'", scalar(value));
- g_debug("%s: adding path '%s' of cost: %d", cur_netdef->id, scalar(key), v);
+ g_debug("%s: adding path '%s' of cost: %d", npp->current.netdef->id, scalar(key), v);
*ref_ptr = v;
}
@@ -1525,7 +1499,7 @@ handle_bridge_path_cost(yaml_document_t* doc, yaml_node_t* node, const void* dat
}
static gboolean
-handle_bridge_port_priority(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_bridge_port_priority(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
for (yaml_node_pair_t* entry = node->data.mapping.pairs.start; entry < node->data.mapping.pairs.top; entry++) {
yaml_node_t* key, *value;
@@ -1534,26 +1508,26 @@ handle_bridge_port_priority(yaml_document_t* doc, yaml_node_t* node, const void*
NetplanNetDefinition *component;
guint* ref_ptr;
- key = yaml_document_get_node(doc, entry->key);
- assert_type(key, YAML_SCALAR_NODE);
- value = yaml_document_get_node(doc, entry->value);
- assert_type(value, YAML_SCALAR_NODE);
+ key = yaml_document_get_node(&npp->doc, entry->key);
+ assert_type(npp, key, YAML_SCALAR_NODE);
+ value = yaml_document_get_node(&npp->doc, entry->value);
+ assert_type(npp, value, YAML_SCALAR_NODE);
- component = g_hash_table_lookup(netdefs, scalar(key));
+ component = g_hash_table_lookup(npp->parsed_defs, scalar(key));
if (!component) {
- add_missing_node(key);
+ add_missing_node(npp, key);
} else {
ref_ptr = ((guint*) ((void*) component + GPOINTER_TO_UINT(data)));
if (*ref_ptr)
- return yaml_error(node, error, "%s: interface '%s' already has a port priority of %u",
- cur_netdef->id, scalar(key), *ref_ptr);
+ return yaml_error(npp, node, error, "%s: interface '%s' already has a port priority of %u",
+ npp->current.netdef->id, scalar(key), *ref_ptr);
v = g_ascii_strtoull(scalar(value), &endptr, 10);
if (*endptr != '\0' || v > 63)
- return yaml_error(node, error, "invalid port priority value (must be between 0 and 63): %s",
+ return yaml_error(npp, node, error, "invalid port priority value (must be between 0 and 63): %s",
scalar(value));
- g_debug("%s: adding port '%s' of priority: %d", cur_netdef->id, scalar(key), v);
+ g_debug("%s: adding port '%s' of priority: %d", npp->current.netdef->id, scalar(key), v);
*ref_ptr = v;
}
@@ -1574,11 +1548,11 @@ static const mapping_entry_handler bridge_params_handlers[] = {
};
static gboolean
-handle_bridge(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_bridge(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- cur_netdef->custom_bridging = TRUE;
- cur_netdef->bridge_params.stp = TRUE;
- return process_mapping(doc, node, bridge_params_handlers, NULL, error);
+ npp->current.netdef->custom_bridging = TRUE;
+ npp->current.netdef->bridge_params.stp = TRUE;
+ return process_mapping(npp, node, bridge_params_handlers, NULL, error);
}
/****************************************************
@@ -1601,59 +1575,63 @@ static const mapping_entry_handler routes_handlers[] = {
};
static gboolean
-handle_routes(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_routes(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- if (!cur_netdef->routes)
- cur_netdef->routes = g_array_new(FALSE, TRUE, sizeof(NetplanIPRoute*));
+ if (!npp->current.netdef->routes)
+ npp->current.netdef->routes = g_array_new(FALSE, TRUE, sizeof(NetplanIPRoute*));
/* Avoid adding the same routes in a 2nd parsing pass by comparing
* the array size to the YAML sequence size. Skip if they are equal. */
guint item_count = node->data.sequence.items.top - node->data.sequence.items.start;
- if (cur_netdef->routes->len == item_count) {
- g_debug("%s: all routes have already been added", cur_netdef->id);
+ if (npp->current.netdef->routes->len == item_count) {
+ g_debug("%s: all routes have already been added", npp->current.netdef->id);
return TRUE;
}
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
- assert_type(entry, YAML_MAPPING_NODE);
-
- g_assert(cur_route == NULL);
- cur_route = g_new0(NetplanIPRoute, 1);
- cur_route->type = g_strdup("unicast");
- cur_route->scope = g_strdup("global");
- cur_route->family = G_MAXUINT; /* 0 is a valid family ID */
- cur_route->metric = NETPLAN_METRIC_UNSPEC; /* 0 is a valid metric */
- cur_route->table = NETPLAN_ROUTE_TABLE_UNSPEC;
- g_debug("%s: adding new route", cur_netdef->id);
-
- if (!process_mapping(doc, entry, routes_handlers, NULL, error))
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
+ NetplanIPRoute* route;
+
+ assert_type(npp, entry, YAML_MAPPING_NODE);
+
+ g_assert(npp->current.route == NULL);
+ route = g_new0(NetplanIPRoute, 1);
+ route->type = g_strdup("unicast");
+ route->scope = g_strdup("global");
+ route->family = G_MAXUINT; /* 0 is a valid family ID */
+ route->metric = NETPLAN_METRIC_UNSPEC; /* 0 is a valid metric */
+ route->table = NETPLAN_ROUTE_TABLE_UNSPEC;
+ g_debug("%s: adding new route", npp->current.netdef->id);
+
+ npp->current.route = route;
+
+ if (!process_mapping(npp, entry, routes_handlers, NULL, error))
goto err;
- if ( ( g_ascii_strcasecmp(cur_route->scope, "link") == 0
- || g_ascii_strcasecmp(cur_route->scope, "host") == 0)
- && !cur_route->to) {
- yaml_error(node, error, "link and host routes must specify a 'to' IP");
+ if ( ( g_ascii_strcasecmp(route->scope, "link") == 0
+ || g_ascii_strcasecmp(route->scope, "host") == 0)
+ && !route->to) {
+ yaml_error(npp, node, error, "link and host routes must specify a 'to' IP");
goto err;
- } else if ( g_ascii_strcasecmp(cur_route->type, "unicast") == 0
- && g_ascii_strcasecmp(cur_route->scope, "global") == 0
- && (!cur_route->to || !cur_route->via)) {
- yaml_error(node, error, "global unicast route must include both a 'to' and 'via' IP");
+ } else if ( g_ascii_strcasecmp(route->type, "unicast") == 0
+ && g_ascii_strcasecmp(route->scope, "global") == 0
+ && (!route->to || !route->via)) {
+ yaml_error(npp, node, error, "global unicast route must include both a 'to' and 'via' IP");
goto err;
- } else if (g_ascii_strcasecmp(cur_route->type, "unicast") != 0 && !cur_route->to) {
- yaml_error(node, error, "non-unicast routes must specify a 'to' IP");
+ } else if (g_ascii_strcasecmp(route->type, "unicast") != 0 && !route->to) {
+ yaml_error(npp, node, error, "non-unicast routes must specify a 'to' IP");
goto err;
}
- g_array_append_val(cur_netdef->routes, cur_route);
- cur_route = NULL;
+ g_array_append_val(npp->current.netdef->routes, route);
+ npp->current.route = NULL;
}
return TRUE;
err:
- if (cur_route) {
- g_free(cur_route);
- cur_route = NULL;
+ if (npp->current.route) {
+ g_free(npp->current.route);
+ npp->current.route = NULL;
}
return FALSE;
}
@@ -1669,33 +1647,34 @@ static const mapping_entry_handler ip_rules_handlers[] = {
};
static gboolean
-handle_ip_rules(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_ip_rules(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
gboolean ret;
- cur_ip_rule = g_new0(NetplanIPRule, 1);
- cur_ip_rule->family = G_MAXUINT; /* 0 is a valid family ID */
- cur_ip_rule->priority = NETPLAN_IP_RULE_PRIO_UNSPEC;
- cur_ip_rule->table = NETPLAN_ROUTE_TABLE_UNSPEC;
- cur_ip_rule->tos = NETPLAN_IP_RULE_TOS_UNSPEC;
- cur_ip_rule->fwmark = NETPLAN_IP_RULE_FW_MARK_UNSPEC;
+ NetplanIPRule* ip_rule = g_new0(NetplanIPRule, 1);
+ ip_rule->family = G_MAXUINT; /* 0 is a valid family ID */
+ ip_rule->priority = NETPLAN_IP_RULE_PRIO_UNSPEC;
+ ip_rule->table = NETPLAN_ROUTE_TABLE_UNSPEC;
+ ip_rule->tos = NETPLAN_IP_RULE_TOS_UNSPEC;
+ ip_rule->fwmark = NETPLAN_IP_RULE_FW_MARK_UNSPEC;
+
+ npp->current.ip_rule = ip_rule;
+ ret = process_mapping(npp, entry, ip_rules_handlers, NULL, error);
+ npp->current.ip_rule = NULL;
- ret = process_mapping(doc, entry, ip_rules_handlers, NULL, error);
- if (ret && !cur_ip_rule->from && !cur_ip_rule->to)
- ret = yaml_error(node, error, "IP routing policy must include either a 'from' or 'to' IP");
+ if (ret && !ip_rule->from && !ip_rule->to)
+ ret = yaml_error(npp, node, error, "IP routing policy must include either a 'from' or 'to' IP");
if (!ret) {
- g_free(cur_ip_rule); /* XXX: do an in-depth cleaning */
- cur_ip_rule = NULL;
+ ip_rule_clear(&ip_rule);
return FALSE;
}
- if (!cur_netdef->ip_rules)
- cur_netdef->ip_rules = g_array_new(FALSE, FALSE, sizeof(NetplanIPRule*));
- g_array_append_val(cur_netdef->ip_rules, cur_ip_rule);
- cur_ip_rule = NULL;
+ if (!npp->current.netdef->ip_rules)
+ npp->current.netdef->ip_rules = g_array_new(FALSE, FALSE, sizeof(NetplanIPRule*));
+ g_array_append_val(npp->current.netdef->ip_rules, ip_rule);
}
return TRUE;
}
@@ -1705,60 +1684,60 @@ handle_ip_rules(yaml_document_t* doc, yaml_node_t* node, const void* _, GError**
****************************************************/
static gboolean
-handle_arp_ip_targets(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_arp_ip_targets(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- if (!cur_netdef->bond_params.arp_ip_targets) {
- cur_netdef->bond_params.arp_ip_targets = g_array_new(FALSE, FALSE, sizeof(char *));
+ if (!npp->current.netdef->bond_params.arp_ip_targets) {
+ npp->current.netdef->bond_params.arp_ip_targets = g_array_new(FALSE, FALSE, sizeof(char *));
}
/* Avoid adding the same arp_ip_targets in a 2nd parsing pass by comparing
* the array size to the YAML sequence size. Skip if they are equal. */
guint item_count = node->data.sequence.items.top - node->data.sequence.items.start;
- if (cur_netdef->bond_params.arp_ip_targets->len == item_count) {
- g_debug("%s: all arp ip targets have already been added", cur_netdef->id);
+ if (npp->current.netdef->bond_params.arp_ip_targets->len == item_count) {
+ g_debug("%s: all arp ip targets have already been added", npp->current.netdef->id);
return TRUE;
}
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
g_autofree char* addr = NULL;
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
- assert_type(entry, YAML_SCALAR_NODE);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
addr = g_strdup(scalar(entry));
/* is it an IPv4 address? */
if (is_ip4_address(addr)) {
char* s = g_strdup(scalar(entry));
- g_array_append_val(cur_netdef->bond_params.arp_ip_targets, s);
+ g_array_append_val(npp->current.netdef->bond_params.arp_ip_targets, s);
continue;
}
- return yaml_error(node, error, "malformed address '%s', must be X.X.X.X or X:X:X:X:X:X:X:X", scalar(entry));
+ return yaml_error(npp, node, error, "malformed address '%s', must be X.X.X.X or X:X:X:X:X:X:X:X", scalar(entry));
}
return TRUE;
}
static gboolean
-handle_bond_primary_slave(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_bond_primary_slave(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
NetplanNetDefinition *component;
char** ref_ptr;
- component = g_hash_table_lookup(netdefs, scalar(node));
+ component = g_hash_table_lookup(npp->parsed_defs, scalar(node));
if (!component) {
- add_missing_node(node);
+ add_missing_node(npp, node);
} else {
/* If this is not the primary pass, the primary slave might already be equally set. */
- if (!g_strcmp0(cur_netdef->bond_params.primary_slave, scalar(node))) {
+ if (!g_strcmp0(npp->current.netdef->bond_params.primary_slave, scalar(node))) {
return TRUE;
- } else if (cur_netdef->bond_params.primary_slave)
- return yaml_error(node, error, "%s: bond already has a primary slave: %s",
- cur_netdef->id, cur_netdef->bond_params.primary_slave);
+ } else if (npp->current.netdef->bond_params.primary_slave)
+ return yaml_error(npp, node, error, "%s: bond already has a primary slave: %s",
+ npp->current.netdef->id, npp->current.netdef->bond_params.primary_slave);
ref_ptr = ((char**) ((void*) component + GPOINTER_TO_UINT(data)));
*ref_ptr = g_strdup(scalar(node));
- cur_netdef->bond_params.primary_slave = g_strdup(scalar(node));
+ npp->current.netdef->bond_params.primary_slave = g_strdup(scalar(node));
}
return TRUE;
@@ -1793,26 +1772,26 @@ static const mapping_entry_handler bond_params_handlers[] = {
};
static gboolean
-handle_bonding(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_bonding(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- return process_mapping(doc, node, bond_params_handlers, NULL, error);
+ return process_mapping(npp, node, bond_params_handlers, NULL, error);
}
static gboolean
-handle_dhcp_identifier(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_dhcp_identifier(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_free(cur_netdef->dhcp_identifier);
+ g_free(npp->current.netdef->dhcp_identifier);
/* "duid" is the default case, so we don't store it. */
if (g_ascii_strcasecmp(scalar(node), "duid") != 0)
- cur_netdef->dhcp_identifier = g_strdup(scalar(node));
+ npp->current.netdef->dhcp_identifier = g_strdup(scalar(node));
else
- cur_netdef->dhcp_identifier = NULL;
+ npp->current.netdef->dhcp_identifier = NULL;
- if (cur_netdef->dhcp_identifier == NULL ||
- g_ascii_strcasecmp(cur_netdef->dhcp_identifier, "mac") == 0)
+ if (npp->current.netdef->dhcp_identifier == NULL ||
+ g_ascii_strcasecmp(npp->current.netdef->dhcp_identifier, "mac") == 0)
return TRUE;
- return yaml_error(node, error, "invalid DHCP client identifier type '%s'", cur_netdef->dhcp_identifier);
+ return yaml_error(npp, node, error, "invalid DHCP client identifier type '%s'", npp->current.netdef->dhcp_identifier);
}
/****************************************************
@@ -1820,7 +1799,7 @@ handle_dhcp_identifier(yaml_document_t* doc, yaml_node_t* node, const void* data
****************************************************/
static gboolean
-handle_tunnel_addr(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_tunnel_addr(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
g_autofree char* addr = NULL;
char* prefix_len;
@@ -1829,21 +1808,21 @@ handle_tunnel_addr(yaml_document_t* doc, yaml_node_t* node, const void* data, GE
addr = g_strdup(scalar(node));
prefix_len = strrchr(addr, '/');
if (prefix_len)
- return yaml_error(node, error, "address '%s' should not include /prefixlength", scalar(node));
+ return yaml_error(npp, node, error, "address '%s' should not include /prefixlength", scalar(node));
/* is it an IPv4 address? */
if (is_ip4_address(addr))
- return handle_netdef_ip4(doc, node, data, error);
+ return handle_netdef_ip4(npp, node, data, error);
/* is it an IPv6 address? */
if (is_ip6_address(addr))
- return handle_netdef_ip6(doc, node, data, error);
+ return handle_netdef_ip6(npp, node, data, error);
- return yaml_error(node, error, "malformed address '%s', must be X.X.X.X or X:X:X:X:X:X:X:X", scalar(node));
+ return yaml_error(npp, node, error, "malformed address '%s', must be X.X.X.X or X:X:X:X:X:X:X:X", scalar(node));
}
static gboolean
-handle_tunnel_mode(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_tunnel_mode(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
const char *key = scalar(node);
NetplanTunnelMode i;
@@ -1851,12 +1830,12 @@ handle_tunnel_mode(yaml_document_t* doc, yaml_node_t* node, const void* _, GErro
// Skip over unknown (0) tunnel mode.
for (i = 1; i < NETPLAN_TUNNEL_MODE_MAX_; ++i) {
if (g_strcmp0(netplan_tunnel_mode_name(i), key) == 0) {
- cur_netdef->tunnel.mode = i;
+ npp->current.netdef->tunnel.mode = i;
return TRUE;
}
}
- return yaml_error(node, error, "%s: tunnel mode '%s' is not supported", cur_netdef->id, key);
+ return yaml_error(npp, node, error, "%s: tunnel mode '%s' is not supported", npp->current.netdef->id, key);
}
static const mapping_entry_handler tunnel_keys_handlers[] = {
@@ -1867,7 +1846,7 @@ static const mapping_entry_handler tunnel_keys_handlers[] = {
};
static gboolean
-handle_tunnel_key_mapping(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_tunnel_key_mapping(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
gboolean ret = FALSE;
@@ -1875,15 +1854,15 @@ handle_tunnel_key_mapping(yaml_document_t* doc, yaml_node_t* node, const void* _
* single scalar with the same key to use for both input, output and private
* keys, or a mapping where one can specify each. */
if (node->type == YAML_SCALAR_NODE) {
- ret = handle_netdef_str(doc, node, netdef_offset(tunnel.input_key), error);
+ ret = handle_netdef_str(npp, node, netdef_offset(tunnel.input_key), error);
if (ret)
- ret = handle_netdef_str(doc, node, netdef_offset(tunnel.output_key), error);
+ ret = handle_netdef_str(npp, node, netdef_offset(tunnel.output_key), error);
if (ret)
- ret = handle_netdef_str(doc, node, netdef_offset(tunnel.private_key), error);
+ ret = handle_netdef_str(npp, node, netdef_offset(tunnel.private_key), error);
} else if (node->type == YAML_MAPPING_NODE)
- ret = process_mapping(doc, node, tunnel_keys_handlers, NULL, error);
+ ret = process_mapping(npp, node, tunnel_keys_handlers, NULL, error);
else
- return yaml_error(node, error, "invalid type for 'key[s]': must be a scalar or mapping");
+ return yaml_error(npp, node, error, "invalid type for 'key[s]': must be a scalar or mapping");
return ret;
}
@@ -1893,10 +1872,10 @@ handle_tunnel_key_mapping(yaml_document_t* doc, yaml_node_t* node, const void* _
* @data: pointer to the const char* field to write
*/
static gboolean
-handle_wireguard_peer_str(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_wireguard_peer_str(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_wireguard_peer);
- return handle_generic_str(doc, node, cur_wireguard_peer, data, error);
+ g_assert(npp->current.wireguard_peer);
+ return handle_generic_str(npp, node, npp->current.wireguard_peer, data, error);
}
/**
@@ -1904,21 +1883,21 @@ handle_wireguard_peer_str(yaml_document_t* doc, yaml_node_t* node, const void* d
* @data: pointer to the guint field to write
*/
static gboolean
-handle_wireguard_peer_guint(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_wireguard_peer_guint(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- g_assert(cur_wireguard_peer);
- return handle_generic_guint(doc, node, cur_wireguard_peer, data, error);
+ g_assert(npp->current.wireguard_peer);
+ return handle_generic_guint(npp, node, npp->current.wireguard_peer, data, error);
}
static gboolean
-handle_wireguard_allowed_ips(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_wireguard_allowed_ips(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- return handle_generic_addresses(doc, node, FALSE, &(cur_wireguard_peer->allowed_ips),
- &(cur_wireguard_peer->allowed_ips), error);
+ return handle_generic_addresses(npp, node, FALSE, &(npp->current.wireguard_peer->allowed_ips),
+ &(npp->current.wireguard_peer->allowed_ips), error);
}
static gboolean
-handle_wireguard_endpoint(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_wireguard_endpoint(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
g_autofree char* endpoint = NULL;
char* port;
@@ -1928,13 +1907,13 @@ handle_wireguard_endpoint(yaml_document_t* doc, yaml_node_t* node, const void* _
endpoint = g_strdup(scalar(node));
/* absolute minimal length of endpoint is 3 chars: 'h:8' */
if (strlen(endpoint) < 3) {
- return yaml_error(node, error, "invalid endpoint address or hostname '%s'", scalar(node));
+ return yaml_error(npp, node, error, "invalid endpoint address or hostname '%s'", scalar(node));
}
if (endpoint[0] == '[') {
/* this is an ipv6 endpoint in [ad:rr:ee::ss]:port form */
char *endbrace = strrchr(endpoint, ']');
if (!endbrace)
- return yaml_error(node, error, "invalid address in endpoint '%s'", scalar(node));
+ return yaml_error(npp, node, error, "invalid address in endpoint '%s'", scalar(node));
address = endpoint + 1;
*endbrace = '\0';
port = strrchr(endbrace + 1, ':');
@@ -1944,16 +1923,16 @@ handle_wireguard_endpoint(yaml_document_t* doc, yaml_node_t* node, const void* _
}
/* split off :port */
if (!port)
- return yaml_error(node, error, "endpoint '%s' is missing :port", scalar(node));
+ return yaml_error(npp, node, error, "endpoint '%s' is missing :port", scalar(node));
*port = '\0';
port++; /* skip former ':' into first char of port */
port_num = g_ascii_strtoull(port, NULL, 10);
if (port_num > 65535)
- return yaml_error(node, error, "invalid port in endpoint '%s'", scalar(node));
+ return yaml_error(npp, node, error, "invalid port in endpoint '%s'", scalar(node));
if (is_ip4_address(address) || is_ip6_address(address) || is_hostname(address)) {
- return handle_wireguard_peer_str(doc, node, wireguard_peer_offset(endpoint), error);
+ return handle_wireguard_peer_str(npp, node, wireguard_peer_offset(endpoint), error);
}
- return yaml_error(node, error, "invalid endpoint address or hostname '%s'", scalar(node));
+ return yaml_error(npp, node, error, "invalid endpoint address or hostname '%s'", scalar(node));
}
static const mapping_entry_handler wireguard_peer_keys_handlers[] = {
@@ -1963,9 +1942,9 @@ static const mapping_entry_handler wireguard_peer_keys_handlers[] = {
};
static gboolean
-handle_wireguard_peer_key_mapping(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_wireguard_peer_key_mapping(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- return process_mapping(doc, node, wireguard_peer_keys_handlers, NULL, error);
+ return process_mapping(npp, node, wireguard_peer_keys_handlers, NULL, error);
}
const mapping_entry_handler wireguard_peer_handlers[] = {
@@ -1977,36 +1956,34 @@ const mapping_entry_handler wireguard_peer_handlers[] = {
};
static gboolean
-handle_wireguard_peers(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_wireguard_peers(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- if (!cur_netdef->wireguard_peers)
- cur_netdef->wireguard_peers = g_array_new(FALSE, TRUE, sizeof(NetplanWireguardPeer*));
+ if (!npp->current.netdef->wireguard_peers)
+ npp->current.netdef->wireguard_peers = g_array_new(FALSE, TRUE, sizeof(NetplanWireguardPeer*));
/* Avoid adding the same peers in a 2nd parsing pass by comparing
* the array size to the YAML sequence size. Skip if they are equal. */
guint item_count = node->data.sequence.items.top - node->data.sequence.items.start;
- if (cur_netdef->wireguard_peers->len == item_count) {
- g_debug("%s: all wireguard peers have already been added", cur_netdef->id);
+ if (npp->current.netdef->wireguard_peers->len == item_count) {
+ g_debug("%s: all wireguard peers have already been added", npp->current.netdef->id);
return TRUE;
}
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
- assert_type(entry, YAML_MAPPING_NODE);
-
- g_assert(cur_wireguard_peer == NULL);
- cur_wireguard_peer = g_new0(NetplanWireguardPeer, 1);
- cur_wireguard_peer->allowed_ips = g_array_new(FALSE, FALSE, sizeof(char*));
- g_debug("%s: adding new wireguard peer", cur_netdef->id);
-
- if (!process_mapping(doc, entry, wireguard_peer_handlers, NULL, error)) {
- g_array_free(cur_wireguard_peer->allowed_ips, TRUE);
- g_free(cur_wireguard_peer); /* TODO: in-depth cleaning ! */
- cur_wireguard_peer = NULL;
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
+ assert_type(npp, entry, YAML_MAPPING_NODE);
+
+ g_assert(npp->current.wireguard_peer == NULL);
+ npp->current.wireguard_peer = g_new0(NetplanWireguardPeer, 1);
+ npp->current.wireguard_peer->allowed_ips = g_array_new(FALSE, FALSE, sizeof(char*));
+ g_debug("%s: adding new wireguard peer", npp->current.netdef->id);
+
+ if (!process_mapping(npp, entry, wireguard_peer_handlers, NULL, error)) {
+ wireguard_peer_clear(&npp->current.wireguard_peer);
return FALSE;
}
- g_array_append_val(cur_netdef->wireguard_peers, cur_wireguard_peer);
- cur_wireguard_peer = NULL;
+ g_array_append_val(npp->current.netdef->wireguard_peers, npp->current.wireguard_peer);
+ npp->current.wireguard_peer = NULL;
}
return TRUE;
}
@@ -2016,40 +1993,40 @@ handle_wireguard_peers(yaml_document_t* doc, yaml_node_t* node, const void* _, G
****************************************************/
static gboolean
-handle_ovs_bond_lacp(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ovs_bond_lacp(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (cur_netdef->type != NETPLAN_DEF_TYPE_BOND)
- return yaml_error(node, error, "Key 'lacp' is only valid for interface type 'openvswitch bond'");
+ if (npp->current.netdef->type != NETPLAN_DEF_TYPE_BOND)
+ return yaml_error(npp, node, error, "Key 'lacp' is only valid for interface type 'openvswitch bond'");
if (g_strcmp0(scalar(node), "active") && g_strcmp0(scalar(node), "passive") && g_strcmp0(scalar(node), "off"))
- return yaml_error(node, error, "Value of 'lacp' needs to be 'active', 'passive' or 'off");
+ return yaml_error(npp, node, error, "Value of 'lacp' needs to be 'active', 'passive' or 'off");
- return handle_netdef_str(doc, node, data, error);
+ return handle_netdef_str(npp, node, data, error);
}
static gboolean
-handle_ovs_bridge_bool(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ovs_bridge_bool(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (cur_netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
- return yaml_error(node, error, "Key is only valid for interface type 'openvswitch bridge'");
+ if (npp->current.netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
+ return yaml_error(npp, node, error, "Key is only valid for interface type 'openvswitch bridge'");
- return handle_netdef_bool(doc, node, data, error);
+ return handle_netdef_bool(npp, node, data, error);
}
static gboolean
-handle_ovs_bridge_fail_mode(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ovs_bridge_fail_mode(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (cur_netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
- return yaml_error(node, error, "Key 'fail-mode' is only valid for interface type 'openvswitch bridge'");
+ if (npp->current.netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
+ return yaml_error(npp, node, error, "Key 'fail-mode' is only valid for interface type 'openvswitch bridge'");
if (g_strcmp0(scalar(node), "standalone") && g_strcmp0(scalar(node), "secure"))
- return yaml_error(node, error, "Value of 'fail-mode' needs to be 'standalone' or 'secure'");
+ return yaml_error(npp, node, error, "Value of 'fail-mode' needs to be 'standalone' or 'secure'");
- return handle_netdef_str(doc, node, data, error);
+ return handle_netdef_str(npp, node, data, error);
}
static gboolean
-handle_ovs_protocol(yaml_document_t* doc, yaml_node_t* node, void* entryptr, const void* data, GError** error)
+handle_ovs_protocol(NetplanParser* npp, yaml_node_t* node, void* entryptr, const void* data, GError** error)
{
const char* supported[] = {
"OpenFlow10", "OpenFlow11", "OpenFlow12", "OpenFlow13", "OpenFlow14", "OpenFlow15", "OpenFlow16", NULL
@@ -2059,15 +2036,15 @@ handle_ovs_protocol(yaml_document_t* doc, yaml_node_t* node, void* entryptr, con
GArray** protocols = (GArray**) ((void*) entryptr + offset);
for (yaml_node_item_t *iter = node->data.sequence.items.start; iter < node->data.sequence.items.top; iter++) {
- yaml_node_t *entry = yaml_document_get_node(doc, *iter);
- assert_type(entry, YAML_SCALAR_NODE);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *iter);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
for (i = 0; supported[i] != NULL; ++i)
if (!g_strcmp0(scalar(entry), supported[i]))
break;
if (supported[i] == NULL)
- return yaml_error(node, error, "Unsupported OVS 'protocol' value: %s", scalar(entry));
+ return yaml_error(npp, node, error, "Unsupported OVS 'protocol' value: %s", scalar(entry));
if (!*protocols)
*protocols = g_array_new(FALSE, FALSE, sizeof(char*));
@@ -2079,31 +2056,31 @@ handle_ovs_protocol(yaml_document_t* doc, yaml_node_t* node, void* entryptr, con
}
static gboolean
-handle_ovs_bridge_protocol(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ovs_bridge_protocol(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (cur_netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
- return yaml_error(node, error, "Key 'protocols' is only valid for interface type 'openvswitch bridge'");
+ if (npp->current.netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
+ return yaml_error(npp, node, error, "Key 'protocols' is only valid for interface type 'openvswitch bridge'");
- return handle_ovs_protocol(doc, node, cur_netdef, data, error);
+ return handle_ovs_protocol(npp, node, npp->current.netdef, data, error);
}
static gboolean
-handle_ovs_bridge_controller_connection_mode(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ovs_bridge_controller_connection_mode(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (cur_netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
- return yaml_error(node, error, "Key 'controller.connection-mode' is only valid for interface type 'openvswitch bridge'");
+ if (npp->current.netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
+ return yaml_error(npp, node, error, "Key 'controller.connection-mode' is only valid for interface type 'openvswitch bridge'");
if (g_strcmp0(scalar(node), "in-band") && g_strcmp0(scalar(node), "out-of-band"))
- return yaml_error(node, error, "Value of 'connection-mode' needs to be 'in-band' or 'out-of-band'");
+ return yaml_error(npp, node, error, "Value of 'connection-mode' needs to be 'in-band' or 'out-of-band'");
- return handle_netdef_str(doc, node, data, error);
+ return handle_netdef_str(npp, node, data, error);
}
static gboolean
-handle_ovs_bridge_controller_addresses(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_ovs_bridge_controller_addresses(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- if (cur_netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
- return yaml_error(node, error, "Key 'controller.addresses' is only valid for interface type 'openvswitch bridge'");
+ if (npp->current.netdef->type != NETPLAN_DEF_TYPE_BRIDGE)
+ return yaml_error(npp, node, error, "Key 'controller.addresses' is only valid for interface type 'openvswitch bridge'");
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
gchar** vec = NULL;
@@ -2111,11 +2088,11 @@ handle_ovs_bridge_controller_addresses(yaml_document_t* doc, yaml_node_t* node,
gboolean is_port = FALSE;
gboolean is_unix = FALSE;
- yaml_node_t *entry = yaml_document_get_node(doc, *i);
- assert_type(entry, YAML_SCALAR_NODE);
+ yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
+ assert_type(npp, entry, YAML_SCALAR_NODE);
/* We always need at least one colon */
if (!g_strrstr(scalar(entry), ":"))
- return yaml_error(node, error, "Unsupported OVS controller target: %s", scalar(entry));
+ return yaml_error(npp, node, error, "Unsupported OVS controller target: %s", scalar(entry));
vec = g_strsplit (scalar(entry), ":", 2);
@@ -2123,31 +2100,31 @@ handle_ovs_bridge_controller_addresses(yaml_document_t* doc, yaml_node_t* node,
is_port = !g_strcmp0(vec[0], "ptcp") || !g_strcmp0(vec[0], "pssl");
is_unix = !g_strcmp0(vec[0], "unix") || !g_strcmp0(vec[0], "punix");
- if (!cur_netdef->ovs_settings.controller.addresses)
- cur_netdef->ovs_settings.controller.addresses = g_array_new(FALSE, FALSE, sizeof(char*));
+ if (!npp->current.netdef->ovs_settings.controller.addresses)
+ npp->current.netdef->ovs_settings.controller.addresses = g_array_new(FALSE, FALSE, sizeof(char*));
/* Format: [p]unix:file */
if (is_unix && vec[1] != NULL && vec[2] == NULL) {
char* s = g_strdup(scalar(entry));
- g_array_append_val(cur_netdef->ovs_settings.controller.addresses, s);
+ g_array_append_val(npp->current.netdef->ovs_settings.controller.addresses, s);
g_strfreev(vec);
continue;
/* Format tcp:host[:port] or ssl:host[:port] */
} else if (is_host && validate_ovs_target(TRUE, vec[1])) {
char* s = g_strdup(scalar(entry));
- g_array_append_val(cur_netdef->ovs_settings.controller.addresses, s);
+ g_array_append_val(npp->current.netdef->ovs_settings.controller.addresses, s);
g_strfreev(vec);
continue;
/* Format ptcp:[port][:host] or pssl:[port][:host] */
} else if (is_port && validate_ovs_target(FALSE, vec[1])) {
char* s = g_strdup(scalar(entry));
- g_array_append_val(cur_netdef->ovs_settings.controller.addresses, s);
+ g_array_append_val(npp->current.netdef->ovs_settings.controller.addresses, s);
g_strfreev(vec);
continue;
}
g_strfreev(vec);
- return yaml_error(node, error, "Unsupported OVS controller target: %s", scalar(entry));
+ return yaml_error(npp, node, error, "Unsupported OVS controller target: %s", scalar(entry));
}
return TRUE;
@@ -2172,13 +2149,13 @@ static const mapping_entry_handler ovs_backend_settings_handlers[] = {
};
static gboolean
-handle_ovs_backend(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_ovs_backend(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
GList* values = NULL;
- gboolean ret = process_mapping(doc, node, ovs_backend_settings_handlers, &values, error);
+ gboolean ret = process_mapping(npp, node, ovs_backend_settings_handlers, &values, error);
guint len = g_list_length(values);
- if (cur_netdef->type != NETPLAN_DEF_TYPE_BOND && cur_netdef->type != NETPLAN_DEF_TYPE_BRIDGE) {
+ if (npp->current.netdef->type != NETPLAN_DEF_TYPE_BOND && npp->current.netdef->type != NETPLAN_DEF_TYPE_BRIDGE) {
GList *other_config = g_list_find_custom(values, "other-config", (GCompareFunc) strcmp);
GList *external_ids = g_list_find_custom(values, "external-ids", (GCompareFunc) strcmp);
/* Non-bond/non-bridge interfaces might still be handled by the networkd backend */
@@ -2192,7 +2169,7 @@ handle_ovs_backend(yaml_document_t* doc, yaml_node_t* node, const void* _, GErro
/* Set the renderer for this device to NETPLAN_BACKEND_OVS, implicitly.
* But only if empty "openvswitch: {}" or "openvswitch:" with more than
* "other-config" or "external-ids" keys is given. */
- cur_netdef->backend = NETPLAN_BACKEND_OVS;
+ npp->current.netdef->backend = NETPLAN_BACKEND_OVS;
return ret;
}
@@ -2356,37 +2333,37 @@ static const mapping_entry_handler tunnel_def_handlers[] = {
****************************************************/
static gboolean
-handle_network_version(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_network_version(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
long mangled_version;
mangled_version = strtol(scalar(node), NULL, 10);
if (mangled_version < NETPLAN_VERSION_MIN || mangled_version >= NETPLAN_VERSION_MAX)
- return yaml_error(node, error, "Only version 2 is supported");
+ return yaml_error(npp, node, error, "Only version 2 is supported");
return TRUE;
}
static gboolean
-handle_network_renderer(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_network_renderer(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
- return parse_renderer(node, &global_state.backend, error);
+ return parse_renderer(npp, node, &npp->global_backend, error);
}
static gboolean
-handle_network_ovs_settings_global(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_network_ovs_settings_global(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_generic_map(doc, node, &ovs_settings_global, data, error);
+ return handle_generic_map(npp, node, &npp->global_ovs_settings, data, error);
}
static gboolean
-handle_network_ovs_settings_global_protocol(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_network_ovs_settings_global_protocol(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
- return handle_ovs_protocol(doc, node, &ovs_settings_global, data, error);
+ return handle_ovs_protocol(npp, node, &npp->global_ovs_settings, data, error);
}
static gboolean
-handle_network_ovs_settings_global_ports(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_network_ovs_settings_global_ports(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
yaml_node_t* port = NULL;
yaml_node_t* peer = NULL;
@@ -2395,44 +2372,44 @@ handle_network_ovs_settings_global_ports(yaml_document_t* doc, yaml_node_t* node
NetplanNetDefinition *component = NULL;
for (yaml_node_item_t *iter = node->data.sequence.items.start; iter < node->data.sequence.items.top; iter++) {
- pair = yaml_document_get_node(doc, *iter);
- assert_type(pair, YAML_SEQUENCE_NODE);
+ pair = yaml_document_get_node(&npp->doc, *iter);
+ assert_type(npp, pair, YAML_SEQUENCE_NODE);
item = pair->data.sequence.items.start;
/* A peer port definition must contain exactly 2 ports */
if (item+2 != pair->data.sequence.items.top) {
- return yaml_error(pair, error, "An openvswitch peer port sequence must have exactly two entries");
+ return yaml_error(npp, pair, error, "An openvswitch peer port sequence must have exactly two entries");
}
- port = yaml_document_get_node(doc, *item);
- assert_type(port, YAML_SCALAR_NODE);
- peer = yaml_document_get_node(doc, *(item+1));
- assert_type(peer, YAML_SCALAR_NODE);
+ port = yaml_document_get_node(&npp->doc, *item);
+ assert_type(npp, port, YAML_SCALAR_NODE);
+ peer = yaml_document_get_node(&npp->doc, *(item+1));
+ assert_type(npp, peer, YAML_SCALAR_NODE);
/* Create port 1 netdef */
- component = netdefs ? g_hash_table_lookup(netdefs, scalar(port)) : NULL;
+ component = npp->parsed_defs ? g_hash_table_lookup(npp->parsed_defs, scalar(port)) : NULL;
if (!component) {
- component = netplan_netdef_new(scalar(port), NETPLAN_DEF_TYPE_PORT, NETPLAN_BACKEND_OVS);
- if (g_hash_table_remove(missing_id, scalar(port)))
- missing_ids_found++;
+ component = netplan_netdef_new(npp, scalar(port), NETPLAN_DEF_TYPE_PORT, NETPLAN_BACKEND_OVS);
+ if (g_hash_table_remove(npp->missing_id, scalar(port)))
+ npp->missing_ids_found++;
}
if (component->peer && g_strcmp0(component->peer, scalar(peer)))
- return yaml_error(port, error, "openvswitch port '%s' is already assigned to peer '%s'",
+ return yaml_error(npp, port, error, "openvswitch port '%s' is already assigned to peer '%s'",
component->id, component->peer);
component->peer = g_strdup(scalar(peer));
/* Create port 2 (peer) netdef */
component = NULL;
- component = netdefs ? g_hash_table_lookup(netdefs, scalar(peer)) : NULL;
+ component = npp->parsed_defs ? g_hash_table_lookup(npp->parsed_defs, scalar(peer)) : NULL;
if (!component) {
- component = netplan_netdef_new(scalar(peer), NETPLAN_DEF_TYPE_PORT, NETPLAN_BACKEND_OVS);
- if (g_hash_table_remove(missing_id, scalar(peer)))
- missing_ids_found++;
+ component = netplan_netdef_new(npp, scalar(peer), NETPLAN_DEF_TYPE_PORT, NETPLAN_BACKEND_OVS);
+ if (g_hash_table_remove(npp->missing_id, scalar(peer)))
+ npp->missing_ids_found++;
}
if (component->peer && g_strcmp0(component->peer, scalar(port)))
- return yaml_error(peer, error, "openvswitch port '%s' is already assigned to peer '%s'",
+ return yaml_error(npp, peer, error, "openvswitch port '%s' is already assigned to peer '%s'",
component->id, component->peer);
component->peer = g_strdup(scalar(port));
}
@@ -2444,53 +2421,53 @@ handle_network_ovs_settings_global_ports(yaml_document_t* doc, yaml_node_t* node
* @data: netdef_type (as pointer)
*/
static gboolean
-handle_network_type(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+handle_network_type(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
for (yaml_node_pair_t* entry = node->data.mapping.pairs.start; entry < node->data.mapping.pairs.top; entry++) {
yaml_node_t* key, *value;
const mapping_entry_handler* handlers;
- key = yaml_document_get_node(doc, entry->key);
- if (!assert_valid_id(key, error))
+ key = yaml_document_get_node(&npp->doc, entry->key);
+ if (!assert_valid_id(npp, key, error))
return FALSE;
/* globbing is not allowed for IDs */
if (strpbrk(scalar(key), "*[]?"))
- return yaml_error(key, error, "Definition ID '%s' must not use globbing", scalar(key));
+ return yaml_error(npp, key, error, "Definition ID '%s' must not use globbing", scalar(key));
- value = yaml_document_get_node(doc, entry->value);
+ value = yaml_document_get_node(&npp->doc, entry->value);
/* special-case "renderer:" key to set the per-type backend */
if (strcmp(scalar(key), "renderer") == 0) {
- if (!parse_renderer(value, &backend_cur_type, error))
+ if (!parse_renderer(npp, value, &npp->current.backend, error))
return FALSE;
continue;
}
- assert_type(value, YAML_MAPPING_NODE);
+ assert_type(npp, value, YAML_MAPPING_NODE);
/* At this point we've seen a new starting definition, if it has been
* already mentioned in another netdef, removing it from our "missing"
* list. */
- if(g_hash_table_remove(missing_id, scalar(key)))
- missing_ids_found++;
+ if(g_hash_table_remove(npp->missing_id, scalar(key)))
+ npp->missing_ids_found++;
- cur_netdef = netdefs ? g_hash_table_lookup(netdefs, scalar(key)) : NULL;
- if (cur_netdef) {
+ npp->current.netdef = npp->parsed_defs ? g_hash_table_lookup(npp->parsed_defs, scalar(key)) : NULL;
+ if (npp->current.netdef) {
/* already exists, overriding/amending previous definition */
- if (cur_netdef->type != GPOINTER_TO_UINT(data))
- return yaml_error(key, error, "Updated definition '%s' changes device type", scalar(key));
+ if (npp->current.netdef->type != GPOINTER_TO_UINT(data))
+ return yaml_error(npp, key, error, "Updated definition '%s' changes device type", scalar(key));
} else {
- cur_netdef = netplan_netdef_new(scalar(key), GPOINTER_TO_UINT(data), backend_cur_type);
+ npp->current.netdef = netplan_netdef_new(npp, scalar(key), GPOINTER_TO_UINT(data), npp->current.backend);
}
- g_assert(cur_filename);
- cur_netdef->filename = g_strdup(cur_filename);
+ g_assert(npp->current.filename);
+ npp->current.netdef->filename = g_strdup(npp->current.filename);
// XXX: breaks multi-pass parsing.
- //if (!g_hash_table_add(ids_in_file, cur_netdef->id))
- // return yaml_error(key, error, "Duplicate net definition ID '%s'", cur_netdef->id);
+ //if (!g_hash_table_add(ids_in_file, npp->current.netdef->id))
+ // return yaml_error(npp, key, error, "Duplicate net definition ID '%s'", npp->current.netdef->id);
/* and fill it with definitions */
- switch (cur_netdef->type) {
+ switch (npp->current.netdef->type) {
case NETPLAN_DEF_TYPE_BOND: handlers = bond_def_handlers; break;
case NETPLAN_DEF_TYPE_BRIDGE: handlers = bridge_def_handlers; break;
case NETPLAN_DEF_TYPE_ETHERNET: handlers = ethernet_def_handlers; break;
@@ -2499,24 +2476,24 @@ handle_network_type(yaml_document_t* doc, yaml_node_t* node, const void* data, G
case NETPLAN_DEF_TYPE_VLAN: handlers = vlan_def_handlers; break;
case NETPLAN_DEF_TYPE_WIFI: handlers = wifi_def_handlers; break;
case NETPLAN_DEF_TYPE_NM:
- g_warning("netplan: %s: handling NetworkManager passthrough device, settings are not fully supported.", cur_netdef->id);
+ g_warning("netplan: %s: handling NetworkManager passthrough device, settings are not fully supported.", npp->current.netdef->id);
handlers = ethernet_def_handlers;
break;
default: g_assert_not_reached(); // LCOV_EXCL_LINE
}
- if (!process_mapping(doc, value, handlers, NULL, error))
+ if (!process_mapping(npp, value, handlers, NULL, error))
return FALSE;
/* validate definition-level conditions */
- if (!validate_netdef_grammar(cur_netdef, value, error))
+ if (!validate_netdef_grammar(npp, npp->current.netdef, value, error))
return FALSE;
/* convenience shortcut: physical device without match: means match
* name on ID */
- if (cur_netdef->type < NETPLAN_DEF_TYPE_VIRTUAL && !cur_netdef->has_match)
- set_str_if_null(cur_netdef->match.original_name, cur_netdef->id);
+ if (npp->current.netdef->type < NETPLAN_DEF_TYPE_VIRTUAL && !npp->current.netdef->has_match)
+ set_str_if_null(npp->current.netdef->match.original_name, npp->current.netdef->id);
}
- backend_cur_type = NETPLAN_BACKEND_NONE;
+ npp->current.backend = NETPLAN_BACKEND_NONE;
return TRUE;
}
@@ -2528,13 +2505,13 @@ static const mapping_entry_handler ovs_global_ssl_handlers[] = {
};
static gboolean
-handle_ovs_global_ssl(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
+handle_ovs_global_ssl(NetplanParser* npp, yaml_node_t* node, const void* _, GError** error)
{
gboolean ret;
- cur_auth = &(ovs_settings_global.ssl);
- ret = process_mapping(doc, node, ovs_global_ssl_handlers, NULL, error);
- cur_auth = NULL;
+ npp->current.auth = &(npp->global_ovs_settings.ssl);
+ ret = process_mapping(npp, node, ovs_global_ssl_handlers, NULL, error);
+ npp->current.auth = NULL;
return ret;
}
@@ -2576,32 +2553,32 @@ static const mapping_entry_handler root_handlers[] = {
* Handle multiple-pass parsing of the yaml document.
*/
static gboolean
-process_document(yaml_document_t* doc, GError** error)
+process_document(NetplanParser* npp, GError** error)
{
gboolean ret;
int previously_found;
int still_missing;
- g_assert(missing_id == NULL);
- missing_id = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+ g_assert(npp->missing_id == NULL);
+ npp->missing_id = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
do {
g_debug("starting new processing pass");
- previously_found = missing_ids_found;
- missing_ids_found = 0;
+ previously_found = npp->missing_ids_found;
+ npp->missing_ids_found = 0;
g_clear_error(error);
- ret = process_mapping(doc, yaml_document_get_root_node(doc), root_handlers, NULL, error);
+ ret = process_mapping(npp, yaml_document_get_root_node(&npp->doc), root_handlers, NULL, error);
- still_missing = g_hash_table_size(missing_id);
+ still_missing = g_hash_table_size(npp->missing_id);
- if (still_missing > 0 && missing_ids_found == previously_found)
+ if (still_missing > 0 && npp->missing_ids_found == previously_found)
break;
- } while (still_missing > 0 || missing_ids_found > 0);
+ } while (still_missing > 0 || npp->missing_ids_found > 0);
- if (g_hash_table_size(missing_id) > 0) {
+ if (g_hash_table_size(npp->missing_id) > 0) {
GHashTableIter iter;
gpointer key, value;
NetplanMissingNode *missing;
@@ -2610,17 +2587,17 @@ process_document(yaml_document_t* doc, GError** error)
/* Get the first missing identifier we can get from our list, to
* approximate early failure and give the user a meaningful error. */
- g_hash_table_iter_init (&iter, missing_id);
+ g_hash_table_iter_init (&iter, npp->missing_id);
g_hash_table_iter_next (&iter, &key, &value);
missing = (NetplanMissingNode*) value;
- return yaml_error(missing->node, error, "%s: interface '%s' is not defined",
+ return yaml_error(npp, missing->node, error, "%s: interface '%s' is not defined",
missing->netdef_id,
key);
}
- g_hash_table_destroy(missing_id);
- missing_id = NULL;
+ g_hash_table_destroy(npp->missing_id);
+ npp->missing_id = NULL;
return ret;
}
@@ -2628,107 +2605,163 @@ process_document(yaml_document_t* doc, GError** error)
* Parse given YAML file and create/update global "netdefs" list.
*/
gboolean
-netplan_parse_yaml(const char* filename, GError** error)
+netplan_parser_load_yaml(NetplanParser* npp, const char* filename, GError** error)
{
- yaml_document_t doc;
+ yaml_document_t *doc = &npp->doc;
gboolean ret;
- if (!load_yaml(filename, &doc, error))
+ if (!load_yaml(filename, doc, error))
return FALSE;
/* empty file? */
- if (yaml_document_get_root_node(&doc) == NULL)
+ if (yaml_document_get_root_node(doc) == NULL)
return TRUE;
- g_assert(ids_in_file == NULL);
- ids_in_file = g_hash_table_new(g_str_hash, NULL);
+ g_assert(npp->ids_in_file == NULL);
+ npp->ids_in_file = g_hash_table_new(g_str_hash, NULL);
- cur_filename = filename;
- ret = process_document(&doc, error);
+ npp->current.filename = g_strdup(filename);
+ ret = process_document(npp, error);
+ g_free((void *)npp->current.filename);
+ npp->current.filename = NULL;
- cur_filename = NULL;
- cur_netdef = NULL;
- yaml_document_delete(&doc);
- g_hash_table_destroy(ids_in_file);
- ids_in_file = NULL;
+ yaml_document_delete(doc);
+ g_hash_table_destroy(npp->ids_in_file);
+ npp->ids_in_file = NULL;
return ret;
}
static gboolean
-finish_iterator(NetplanNetDefinition* nd, GError **error)
+finish_iterator(const NetplanParser* npp, NetplanNetDefinition* nd, GError **error)
{
/* Take more steps to make sure we always have a backend set for netdefs */
if (nd->backend == NETPLAN_BACKEND_NONE) {
- nd->backend = get_default_backend_for_type(nd->type);
+ nd->backend = get_default_backend_for_type(npp, nd->type);
g_debug("%s: setting default backend to %i", nd->id, nd->backend);
}
/* Do a final pass of validation for backend-specific conditions */
- return validate_backend_rules(nd, error);
+ return validate_backend_rules(npp, nd, error);
}
-/**
- * Post-processing after parsing all config files
- */
-GHashTable *
-netplan_finish_parse(GError** error)
+static gboolean
+insert_kv_into_hash(void *key, void *value, void *hash)
+{
+ g_hash_table_insert(hash, key, value);
+ return TRUE;
+}
+
+gboolean
+netplan_state_import_parser_results(NetplanState* np_state, NetplanParser* npp, GError** error)
{
- if (netdefs) {
+ if (npp->parsed_defs) {
GError *recoverable = NULL;
GHashTableIter iter;
gpointer key, value;
g_debug("We have some netdefs, pass them through a final round of validation");
- if (!validate_default_route_consistency(netdefs, &recoverable)) {
+ if (!validate_default_route_consistency(npp, npp->parsed_defs, &recoverable)) {
g_warning("Problem encountered while validating default route consistency."
"Please set up multiple routing tables and use `routing-policy` instead.\n"
"Error: %s", (recoverable) ? recoverable->message : "");
g_clear_error(&recoverable);
}
- g_hash_table_iter_init (&iter, netdefs);
+
+ g_hash_table_iter_init (&iter, npp->parsed_defs);
while (g_hash_table_iter_next (&iter, &key, &value)) {
- if (!finish_iterator((NetplanNetDefinition *) value, error))
- return NULL;
+ g_assert(np_state->netdefs == NULL ||
+ g_hash_table_lookup(np_state->netdefs, key) == NULL);
+ if (!finish_iterator(npp, (NetplanNetDefinition *) value, error))
+ return FALSE;
g_debug("Configuration is valid");
}
}
- return netdefs;
+
+ if (npp->parsed_defs) {
+ if (!np_state->netdefs)
+ np_state->netdefs = g_hash_table_new(g_str_hash, g_str_equal);
+ g_hash_table_foreach_steal(npp->parsed_defs, insert_kv_into_hash, np_state->netdefs);
+ }
+ np_state->netdefs_ordered = g_list_concat(np_state->netdefs_ordered, npp->ordered);
+ np_state->ovs_settings = npp->global_ovs_settings;
+ np_state->backend = npp->global_backend;
+
+ /* We need to reset those fields manually as we transfered ownership of the underlying
+ data to out. If we don't do this, netplan_clear_parser will deallocate data
+ that we don't own anymore. */
+ npp->parsed_defs = NULL;
+ npp->ordered = NULL;
+ memset(&npp->global_ovs_settings, 0, sizeof(NetplanOVSSettings));
+
+ netplan_parser_reset(npp);
+ return TRUE;
+}
+
+static void
+clear_netdef_from_list(void *def)
+{
+ reset_netdef((NetplanNetDefinition *)def, NETPLAN_DEF_TYPE_NONE, NETPLAN_BACKEND_NONE);
+ g_free(def);
+}
+
+NetplanParser*
+netplan_parser_new()
+{
+ NetplanParser* npp = g_new0(NetplanParser, 1);
+ netplan_parser_reset(npp);
+ return npp;
}
void
-process_input_file(const char* f)
+netplan_parser_reset(NetplanParser* npp)
{
- GError* error = NULL;
+ g_assert(npp != NULL);
+
+ if(npp->parsed_defs) {
+ /* FIXME: make sure that any dynamically allocated netdef data is freed */
+ g_hash_table_destroy(npp->parsed_defs);
+ npp->parsed_defs = NULL;
+ }
+ if(npp->ordered) {
+ g_clear_list(&npp->ordered, clear_netdef_from_list);
+ npp->ordered = NULL;
+ }
+
+ npp->global_backend = NETPLAN_BACKEND_NONE;
+ reset_ovs_settings(&npp->global_ovs_settings);
+
+ /* These pointers are non-owning, it's not our place to free their resources*/
+ npp->current.netdef = NULL;
+ npp->current.auth = NULL;
+
+ access_point_clear(&npp->current.access_point, npp->current.backend);
+ wireguard_peer_clear(&npp->current.wireguard_peer);
+ address_options_clear(&npp->current.addr_options);
+ route_clear(&npp->current.route);
+ ip_rule_clear(&npp->current.ip_rule);
+ g_free((void *)npp->current.filename);
+ npp->current.filename = NULL;
+
+ //LCOV_EXCL_START
+ if (npp->ids_in_file) {
+ g_hash_table_destroy(npp->ids_in_file);
+ npp->ids_in_file = NULL;
+ }
+ //LCOV_EXCL_STOP
- g_debug("Processing input file %s..", f);
- if (!netplan_parse_yaml(f, &error)) {
- g_fprintf(stderr, "%s\n", error->message);
- exit(1);
+ if (npp->missing_id) {
+ g_hash_table_destroy(npp->missing_id);
+ npp->missing_id = NULL;
}
+
+ npp->missing_ids_found = 0;
}
-gboolean
-process_yaml_hierarchy(const char* rootdir)
-{
- glob_t gl;
- /* Files with asciibetically higher names override/append settings from
- * earlier ones (in all config dirs); files in /run/netplan/
- * shadow files in /etc/netplan/ which shadow files in /lib/netplan/.
- * To do that, we put all found files in a hash table, then sort it by
- * file name, and add the entries from /run after the ones from /etc
- * and those after the ones from /lib. */
- if (find_yaml_glob(rootdir, &gl) != 0)
- return FALSE; // LCOV_EXCL_LINE
- /* keys are strdup()ed, free them; values point into the glob_t, don't free them */
- g_autoptr(GHashTable) configs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
- g_autoptr(GList) config_keys = NULL;
-
- for (size_t i = 0; i < gl.gl_pathc; ++i)
- g_hash_table_insert(configs, g_path_get_basename(gl.gl_pathv[i]), gl.gl_pathv[i]);
-
- config_keys = g_list_sort(g_hash_table_get_keys(configs), (GCompareFunc) strcmp);
-
- for (GList* i = config_keys; i != NULL; i = i->next)
- process_input_file(g_hash_table_lookup(configs, i->data));
- return TRUE;
+void
+netplan_parser_clear(NetplanParser** npp_p)
+{
+ NetplanParser* npp = *npp_p;
+ *npp_p = NULL;
+ netplan_parser_reset(npp);
+ g_free(npp);
}
diff --git a/src/types.c b/src/types.c
index a372bb4..b8c967d 100644
--- a/src/types.c
+++ b/src/types.c
@@ -113,7 +113,7 @@ reset_auth_settings(NetplanAuthenticationSettings* auth)
auth->eap_method = NETPLAN_AUTH_EAP_NONE;
}
-static void
+void
reset_ovs_settings(NetplanOVSSettings* settings)
{
settings->mcast_snooping = FALSE;
@@ -331,19 +331,22 @@ clear_netdef_from_list(void *def)
g_free(def);
}
-// LCOV_EXCL_START
NetplanState*
netplan_state_new()
{
- return NULL;
+ NetplanState* np_state = g_new0(NetplanState, 1);
+ netplan_state_reset(np_state);
+ return np_state;
}
void
netplan_state_clear(NetplanState** np_state_p)
{
- g_assert(0);
+ NetplanState* np_state = *np_state_p;
+ *np_state_p = NULL;
+ netplan_state_reset(np_state);
+ g_free(np_state);
}
-// LCOV_EXCL_STOP
void
netplan_state_reset(NetplanState* np_state)
@@ -380,3 +383,43 @@ netplan_state_get_netdefs_size(const NetplanState* np_state)
{
return np_state->netdefs ? g_hash_table_size(np_state->netdefs) : 0;
}
+
+void
+access_point_clear(NetplanWifiAccessPoint** ap, NetplanBackend backend)
+{
+ NetplanWifiAccessPoint* obj = *ap;
+ if (!obj)
+ return;
+ *ap = NULL;
+ free_access_point(NULL, obj, &backend);
+}
+
+#define CLEAR_FROM_FREE(free_fn, clear_fn, type) void clear_fn(type** dest) \
+{ \
+ type* obj; \
+ if (!dest || !(*dest)) return; \
+ obj = *dest; \
+ *dest = NULL; \
+ free_fn(obj);\
+}
+
+CLEAR_FROM_FREE(free_wireguard_peer, wireguard_peer_clear, NetplanWireguardPeer);
+CLEAR_FROM_FREE(free_ip_rules, ip_rule_clear, NetplanIPRule);
+CLEAR_FROM_FREE(free_route, route_clear, NetplanIPRoute);
+CLEAR_FROM_FREE(free_address_options, address_options_clear, NetplanAddressOptions);
+
+NetplanNetDefinition*
+netplan_state_get_netdef(const NetplanState* np_state, const char* id)
+{
+ if (!np_state->netdefs)
+ return NULL;
+ return g_hash_table_lookup(np_state->netdefs, id);
+}
+
+NETPLAN_PUBLIC const char *
+netplan_netdef_get_filename(const NetplanNetDefinition* netdef)
+{
+ if (!netdef)
+ return NULL;
+ return netdef->filename;
+}
diff --git a/src/types.h b/src/types.h
index 6e4ec7f..8ed6400 100644
--- a/src/types.h
+++ b/src/types.h
@@ -431,6 +431,57 @@ struct netplan_state {
NetplanOVSSettings ovs_settings;
};
+struct netplan_parser {
+ yaml_document_t doc;
+ /* Netplan definitions that have already been processed.
+ * Weak references to the nedefs */
+ GHashTable* parsed_defs;
+ /* Same definitions, stored in the order of processing.
+ * Owning structure for the netdefs */
+ GList* ordered;
+ NetplanBackend global_backend;
+ NetplanOVSSettings global_ovs_settings;
+
+ /* Data currently being processed */
+ struct {
+ /* Refs to objects allocated elsewhere */
+ NetplanNetDefinition* netdef;
+ NetplanAuthenticationSettings *auth;
+
+ /* Owned refs, not yet referenced anywhere */
+ NetplanWifiAccessPoint *access_point;
+ NetplanWireguardPeer* wireguard_peer;
+ NetplanAddressOptions* addr_options;
+ NetplanIPRoute* route;
+ NetplanIPRule* ip_rule;
+ const char *filename;
+
+ /* Plain old data representing the backend for which we are
+ * currently parsing. Not necessarily the same as the global
+ * backend. */
+ NetplanBackend backend;
+ } current;
+
+ /* List of "seen" ids not found in netdefs yet by the parser.
+ * These are removed when it exists in this list and we reach the point of
+ * creating a netdef for that id; so by the time we're done parsing the yaml
+ * document it should be empty.
+ *
+ * Keys are not owned, but the values are. Should be created with NULL and g_free
+ * destructors, respectively, so that the cleanup is automatic at destruction.
+ */
+ GHashTable* missing_id;
+
+ /* Set of IDs in currently parsed YAML file, for being able to detect
+ * "duplicate ID within one file" vs. allowing a drop-in to override/amend an
+ * existing definition.
+ *
+ * Appears to be unused?
+ * */
+ GHashTable* ids_in_file;
+ int missing_ids_found;
+};
+
#define NETPLAN_ADVERTISED_RECEIVE_WINDOW_UNSPEC 0
#define NETPLAN_CONGESTION_WINDOW_UNSPEC 0
#define NETPLAN_MTU_UNSPEC 0
@@ -441,4 +492,22 @@ struct netplan_state {
#define NETPLAN_IP_RULE_TOS_UNSPEC G_MAXUINT
void
-reset_netdef(NetplanNetDefinition *netdef, NetplanDefType type, NetplanBackend renderer);
+reset_netdef(NetplanNetDefinition* netdef, NetplanDefType type, NetplanBackend renderer);
+
+void
+reset_ovs_settings(NetplanOVSSettings *settings);
+
+void
+access_point_clear(NetplanWifiAccessPoint** ap, NetplanBackend backend);
+
+void
+wireguard_peer_clear(NetplanWireguardPeer** peer);
+
+void
+address_options_clear(NetplanAddressOptions** options);
+
+void
+ip_rule_clear(NetplanIPRule** rule);
+
+void
+route_clear(NetplanIPRoute** route);
diff --git a/src/util-internal.h b/src/util-internal.h
index a0068ca..7c79481 100644
--- a/src/util-internal.h
+++ b/src/util-internal.h
@@ -66,7 +66,13 @@ const char*
tunnel_mode_to_string(NetplanTunnelMode mode);
NetplanNetDefinition*
-netplan_netdef_new(const char* id, NetplanDefType type, NetplanBackend renderer);
+netplan_netdef_new(NetplanParser* npp, const char* id, NetplanDefType type, NetplanBackend renderer);
+
+const char *
+netplan_parser_get_filename(NetplanParser* npp);
+
+NETPLAN_INTERNAL gboolean
+netplan_parser_load_yaml_hierarchy(NetplanParser* npp, const char* rootdir, GError** error);
NETPLAN_INTERNAL void
process_input_file(const char* f);
diff --git a/src/util.c b/src/util.c
index e6debc4..f87df49 100644
--- a/src/util.c
+++ b/src/util.c
@@ -218,30 +218,40 @@ netplan_delete_connection(const char* id, const char* rootdir)
g_autofree gchar* del = NULL;
g_autoptr(GError) error = NULL;
NetplanNetDefinition* nd = NULL;
+ gboolean ret = TRUE;
+
+ NetplanState* np_state = netplan_state_new();
+ NetplanParser* npp = netplan_parser_new();
/* parse all YAML files */
- if (!process_yaml_hierarchy(rootdir))
- return FALSE; // LCOV_EXCL_LINE
+ if ( !netplan_parser_load_yaml_hierarchy(npp, rootdir, &error)
+ || !netplan_state_import_parser_results(np_state, npp, &error)) {
+ // LCOV_EXCL_START
+ g_fprintf(stderr, "%s\n", error->message);
+ ret = FALSE;
+ goto cleanup;
+ // LCOV_EXCL_STOP
+ }
- netdefs = netplan_finish_parse(&error);
- if (!netdefs) {
+ if (!np_state->netdefs) {
// LCOV_EXCL_START
g_fprintf(stderr, "netplan_delete_connection: %s\n", error->message);
- return FALSE;
+ ret = FALSE;
+ goto cleanup;
// LCOV_EXCL_STOP
}
/* find filename for specified netdef ID */
- nd = g_hash_table_lookup(netdefs, id);
+ nd = g_hash_table_lookup(np_state->netdefs, id);
if (!nd) {
g_warning("netplan_delete_connection: Cannot delete %s, does not exist.", id);
- return FALSE;
+ ret = FALSE;
+ goto cleanup;
}
filename = g_path_get_basename(nd->filename);
filename[strlen(filename) - 5] = '\0'; //stip ".yaml" suffix
del = g_strdup_printf("network.%s.%s=NULL", netplan_def_type_name(nd->type), id);
- netplan_clear_netdefs();
/* TODO: refactor logic to actually be inside the library instead of spawning another process */
const gchar *argv[] = { SBINDIR "/" "netplan", "set", del, "--origin-hint" , filename, NULL, NULL, NULL };
@@ -251,7 +261,12 @@ netplan_delete_connection(const char* id, const char* rootdir)
}
if (getenv("TEST_NETPLAN_CMD") != 0)
argv[0] = getenv("TEST_NETPLAN_CMD");
- return g_spawn_sync(NULL, (gchar**)argv, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ ret = g_spawn_sync(NULL, (gchar**)argv, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+
+cleanup:
+ if (npp) netplan_parser_clear(&npp);
+ if (np_state) netplan_state_clear(&np_state);
+ return ret;
}
gboolean
@@ -302,27 +317,31 @@ netplan_get_id_from_nm_filename(const char* filename, const char* ssid)
return g_strndup(start, id_len);
}
-/**
- * Get the filename from which the given netdef has been parsed.
- * @rootdir: ID of the netdef to be looked up
- * @rootdir: parse files from this root directory
- */
-gchar*
-netplan_get_filename_by_id(const char* netdef_id, const char* rootdir)
+gboolean
+netplan_parser_load_yaml_hierarchy(NetplanParser* npp, const char* rootdir, GError** error)
{
- gchar* filename = NULL;
- netplan_clear_netdefs();
- if (!process_yaml_hierarchy(rootdir))
- return NULL; // LCOV_EXCL_LINE
- GHashTable* netdefs = netplan_finish_parse(NULL);
- if (!netdefs)
- return NULL;
- NetplanNetDefinition* nd = g_hash_table_lookup(netdefs, netdef_id);
- if (!nd)
- return NULL;
- filename = g_strdup(nd->filename);
- netplan_clear_netdefs();
- return filename;
+ glob_t gl;
+ /* Files with asciibetically higher names override/append settings from
+ * earlier ones (in all config dirs); files in /run/netplan/
+ * shadow files in /etc/netplan/ which shadow files in /lib/netplan/.
+ * To do that, we put all found files in a hash table, then sort it by
+ * file name, and add the entries from /run after the ones from /etc
+ * and those after the ones from /lib. */
+ if (find_yaml_glob(rootdir, &gl) != 0)
+ return FALSE; // LCOV_EXCL_LINE
+ /* keys are strdup()ed, free them; values point into the glob_t, don't free them */
+ g_autoptr(GHashTable) configs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+ g_autoptr(GList) config_keys = NULL;
+
+ for (size_t i = 0; i < gl.gl_pathc; ++i)
+ g_hash_table_insert(configs, g_path_get_basename(gl.gl_pathv[i]), gl.gl_pathv[i]);
+
+ config_keys = g_list_sort(g_hash_table_get_keys(configs), (GCompareFunc) strcmp);
+
+ for (GList* i = config_keys; i != NULL; i = i->next)
+ if (!netplan_parser_load_yaml(npp, g_hash_table_lookup(configs, i->data), error))
+ return FALSE;
+ return TRUE;
}
/**
diff --git a/src/validation.c b/src/validation.c
index 7b80559..2e172c7 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -155,7 +155,7 @@ validate_ovs_target(gboolean host_first, gchar* s) {
* Validation for grammar and backend rules.
************************************************/
static gboolean
-validate_tunnel_key(yaml_node_t* node, gchar* key, GError** error)
+validate_tunnel_key(const NetplanParser* npp, yaml_node_t* node, gchar* key, GError** error)
{
/* Tunnel key should be a number or dotted quad, except for wireguard. */
gchar* endptr;
@@ -163,53 +163,53 @@ validate_tunnel_key(yaml_node_t* node, gchar* key, GError** error)
if (*endptr != '\0' || v > G_MAXUINT) {
/* Not a simple uint, try for a dotted quad */
if (!is_ip4_address(key))
- return yaml_error(node, error, "invalid tunnel key '%s'", key);
+ return yaml_error(npp, node, error, "invalid tunnel key '%s'", key);
}
return TRUE;
}
static gboolean
-validate_tunnel_grammar(NetplanNetDefinition* nd, yaml_node_t* node, GError** error)
+validate_tunnel_grammar(const NetplanParser* npp, NetplanNetDefinition* nd, yaml_node_t* node, GError** error)
{
if (nd->tunnel.mode == NETPLAN_TUNNEL_MODE_UNKNOWN)
- return yaml_error(node, error, "%s: missing 'mode' property for tunnel", nd->id);
+ return yaml_error(npp, node, error, "%s: missing 'mode' property for tunnel", nd->id);
if (nd->tunnel.mode == NETPLAN_TUNNEL_MODE_WIREGUARD) {
if (!nd->tunnel.private_key)
- return yaml_error(node, error, "%s: missing 'key' property (private key) for wireguard", nd->id);
+ return yaml_error(npp, node, error, "%s: missing 'key' property (private key) for wireguard", nd->id);
if (nd->tunnel.private_key[0] != '/' && !is_wireguard_key(nd->tunnel.private_key))
- return yaml_error(node, error, "%s: invalid wireguard private key", nd->id);
+ return yaml_error(npp, node, error, "%s: invalid wireguard private key", nd->id);
if (!nd->wireguard_peers || nd->wireguard_peers->len == 0)
- return yaml_error(node, error, "%s: at least one peer is required.", nd->id);
+ return yaml_error(npp, node, error, "%s: at least one peer is required.", nd->id);
for (guint i = 0; i < nd->wireguard_peers->len; i++) {
NetplanWireguardPeer *peer = g_array_index (nd->wireguard_peers, NetplanWireguardPeer*, i);
if (!peer->public_key)
- return yaml_error(node, error, "%s: keys.public is required.", nd->id);
+ return yaml_error(npp, node, error, "%s: keys.public is required.", nd->id);
if (!is_wireguard_key(peer->public_key))
- return yaml_error(node, error, "%s: invalid wireguard public key", nd->id);
+ return yaml_error(npp, node, error, "%s: invalid wireguard public key", nd->id);
if (peer->preshared_key && peer->preshared_key[0] != '/' && !is_wireguard_key(peer->preshared_key))
- return yaml_error(node, error, "%s: invalid wireguard shared key", nd->id);
+ return yaml_error(npp, node, error, "%s: invalid wireguard shared key", nd->id);
if (!peer->allowed_ips || peer->allowed_ips->len == 0)
- return yaml_error(node, error, "%s: 'to' is required to define the allowed IPs.", nd->id);
+ return yaml_error(npp, node, error, "%s: 'to' is required to define the allowed IPs.", nd->id);
if (peer->keepalive > 65535)
- return yaml_error(node, error, "%s: keepalive must be 0-65535 inclusive.", nd->id);
+ return yaml_error(npp, node, error, "%s: keepalive must be 0-65535 inclusive.", nd->id);
}
return TRUE;
} else {
- if (nd->tunnel.input_key && !validate_tunnel_key(node, nd->tunnel.input_key, error))
+ if (nd->tunnel.input_key && !validate_tunnel_key(npp, node, nd->tunnel.input_key, error))
return FALSE;
- if (nd->tunnel.output_key && !validate_tunnel_key(node, nd->tunnel.output_key, error))
+ if (nd->tunnel.output_key && !validate_tunnel_key(npp, node, nd->tunnel.output_key, error))
return FALSE;
}
/* Validate local/remote IPs */
if (!nd->tunnel.local_ip)
- return yaml_error(node, error, "%s: missing 'local' property for tunnel", nd->id);
+ return yaml_error(npp, node, error, "%s: missing 'local' property for tunnel", nd->id);
if (!nd->tunnel.remote_ip)
- return yaml_error(node, error, "%s: missing 'remote' property for tunnel", nd->id);
+ return yaml_error(npp, node, error, "%s: missing 'remote' property for tunnel", nd->id);
if (nd->tunnel_ttl && nd->tunnel_ttl > 255)
- return yaml_error(node, error, "%s: 'ttl' property for tunnel must be in range [1...255]", nd->id);
+ return yaml_error(npp, node, error, "%s: 'ttl' property for tunnel must be in range [1...255]", nd->id);
switch(nd->tunnel.mode) {
case NETPLAN_TUNNEL_MODE_IPIP6:
@@ -218,16 +218,16 @@ validate_tunnel_grammar(NetplanNetDefinition* nd, yaml_node_t* node, GError** er
case NETPLAN_TUNNEL_MODE_IP6GRETAP:
case NETPLAN_TUNNEL_MODE_VTI6:
if (!is_ip6_address(nd->tunnel.local_ip))
- return yaml_error(node, error, "%s: 'local' must be a valid IPv6 address for this tunnel type", nd->id);
+ return yaml_error(npp, node, error, "%s: 'local' must be a valid IPv6 address for this tunnel type", nd->id);
if (!is_ip6_address(nd->tunnel.remote_ip))
- return yaml_error(node, error, "%s: 'remote' must be a valid IPv6 address for this tunnel type", nd->id);
+ return yaml_error(npp, node, error, "%s: 'remote' must be a valid IPv6 address for this tunnel type", nd->id);
break;
default:
if (!is_ip4_address(nd->tunnel.local_ip))
- return yaml_error(node, error, "%s: 'local' must be a valid IPv4 address for this tunnel type", nd->id);
+ return yaml_error(npp, node, error, "%s: 'local' must be a valid IPv4 address for this tunnel type", nd->id);
if (!is_ip4_address(nd->tunnel.remote_ip))
- return yaml_error(node, error, "%s: 'remote' must be a valid IPv4 address for this tunnel type", nd->id);
+ return yaml_error(npp, node, error, "%s: 'remote' must be a valid IPv4 address for this tunnel type", nd->id);
break;
}
@@ -235,7 +235,7 @@ validate_tunnel_grammar(NetplanNetDefinition* nd, yaml_node_t* node, GError** er
}
static gboolean
-validate_tunnel_backend_rules(NetplanNetDefinition* nd, yaml_node_t* node, GError** error)
+validate_tunnel_backend_rules(const NetplanParser* npp, NetplanNetDefinition* nd, yaml_node_t* node, GError** error)
{
/* Backend-specific validation rules for tunnels */
switch (nd->backend) {
@@ -251,7 +251,7 @@ validate_tunnel_backend_rules(NetplanNetDefinition* nd, yaml_node_t* node, GErro
* systemd-networkd has grown ISATAP support in 918049a.
*/
case NETPLAN_TUNNEL_MODE_ISATAP:
- return yaml_error(node, error,
+ return yaml_error(npp, node, error,
"%s: %s tunnel mode is not supported by networkd",
nd->id,
g_ascii_strup(netplan_tunnel_mode_name(nd->tunnel.mode), -1));
@@ -259,9 +259,9 @@ validate_tunnel_backend_rules(NetplanNetDefinition* nd, yaml_node_t* node, GErro
default:
if (nd->tunnel.input_key)
- return yaml_error(node, error, "%s: 'input-key' is not required for this tunnel type", nd->id);
+ return yaml_error(npp, node, error, "%s: 'input-key' is not required for this tunnel type", nd->id);
if (nd->tunnel.output_key)
- return yaml_error(node, error, "%s: 'output-key' is not required for this tunnel type", nd->id);
+ return yaml_error(npp, node, error, "%s: 'output-key' is not required for this tunnel type", nd->id);
break;
}
break;
@@ -275,7 +275,7 @@ validate_tunnel_backend_rules(NetplanNetDefinition* nd, yaml_node_t* node, GErro
case NETPLAN_TUNNEL_MODE_GRETAP:
case NETPLAN_TUNNEL_MODE_IP6GRETAP:
- return yaml_error(node, error,
+ return yaml_error(npp, node, error,
"%s: %s tunnel mode is not supported by NetworkManager",
nd->id,
g_ascii_strup(netplan_tunnel_mode_name(nd->tunnel.mode), -1));
@@ -283,9 +283,9 @@ validate_tunnel_backend_rules(NetplanNetDefinition* nd, yaml_node_t* node, GErro
default:
if (nd->tunnel.input_key)
- return yaml_error(node, error, "%s: 'input-key' is not required for this tunnel type", nd->id);
+ return yaml_error(npp, node, error, "%s: 'input-key' is not required for this tunnel type", nd->id);
if (nd->tunnel.output_key)
- return yaml_error(node, error, "%s: 'output-key' is not required for this tunnel type", nd->id);
+ return yaml_error(npp, node, error, "%s: 'output-key' is not required for this tunnel type", nd->id);
break;
}
break;
@@ -297,9 +297,9 @@ validate_tunnel_backend_rules(NetplanNetDefinition* nd, yaml_node_t* node, GErro
}
gboolean
-validate_netdef_grammar(NetplanNetDefinition* nd, yaml_node_t* node, GError** error)
+validate_netdef_grammar(const NetplanParser* npp, NetplanNetDefinition* nd, yaml_node_t* node, GError** error)
{
- int missing_id_count = g_hash_table_size(missing_id);
+ int missing_id_count = g_hash_table_size(npp->missing_id);
gboolean valid = FALSE;
g_assert(nd->type != NETPLAN_DEF_TYPE_NONE);
@@ -312,41 +312,41 @@ validate_netdef_grammar(NetplanNetDefinition* nd, yaml_node_t* node, GError** er
/* set-name: requires match: */
if (nd->set_name && !nd->has_match)
- return yaml_error(node, error, "%s: 'set-name:' requires 'match:' properties", nd->id);
+ return yaml_error(npp, node, error, "%s: 'set-name:' requires 'match:' properties", nd->id);
if (nd->type == NETPLAN_DEF_TYPE_WIFI && nd->access_points == NULL)
- return yaml_error(node, error, "%s: No access points defined", nd->id);
+ return yaml_error(npp, node, error, "%s: No access points defined", nd->id);
if (nd->type == NETPLAN_DEF_TYPE_VLAN) {
if (!nd->vlan_link)
- return yaml_error(node, error, "%s: missing 'link' property", nd->id);
+ return yaml_error(npp, node, error, "%s: missing 'link' property", nd->id);
nd->vlan_link->has_vlans = TRUE;
if (nd->vlan_id == G_MAXUINT)
- return yaml_error(node, error, "%s: missing 'id' property", nd->id);
+ return yaml_error(npp, node, error, "%s: missing 'id' property", nd->id);
if (nd->vlan_id > 4094)
- return yaml_error(node, error, "%s: invalid id '%u' (allowed values are 0 to 4094)", nd->id, nd->vlan_id);
+ return yaml_error(npp, node, error, "%s: invalid id '%u' (allowed values are 0 to 4094)", nd->id, nd->vlan_id);
}
if (nd->type == NETPLAN_DEF_TYPE_TUNNEL) {
- valid = validate_tunnel_grammar(nd, node, error);
+ valid = validate_tunnel_grammar(npp, nd, node, error);
if (!valid)
goto netdef_grammar_error;
}
if (nd->ip6_addr_gen_mode != NETPLAN_ADDRGEN_DEFAULT && nd->ip6_addr_gen_token)
- return yaml_error(node, error, "%s: ipv6-address-generation and ipv6-address-token are mutually exclusive", nd->id);
+ return yaml_error(npp, node, error, "%s: ipv6-address-generation and ipv6-address-token are mutually exclusive", nd->id);
if (nd->backend == NETPLAN_BACKEND_OVS) {
// LCOV_EXCL_START
if (!g_file_test(OPENVSWITCH_OVS_VSCTL, G_FILE_TEST_EXISTS)) {
/* Tested via integration test */
- return yaml_error(node, error, "%s: The 'ovs-vsctl' tool is required to setup OpenVSwitch interfaces.", nd->id);
+ return yaml_error(npp, node, error, "%s: The 'ovs-vsctl' tool is required to setup OpenVSwitch interfaces.", nd->id);
}
// LCOV_EXCL_STOP
}
if (nd->type == NETPLAN_DEF_TYPE_NM && (!nd->backend_settings.nm.passthrough || !g_datalist_get_data(&nd->backend_settings.nm.passthrough, "connection.type")))
- return yaml_error(node, error, "%s: network type 'nm-devices:' needs to provide a 'connection.type' via passthrough", nd->id);
+ return yaml_error(npp, node, error, "%s: network type 'nm-devices:' needs to provide a 'connection.type' via passthrough", nd->id);
valid = TRUE;
@@ -355,7 +355,7 @@ netdef_grammar_error:
}
gboolean
-validate_backend_rules(NetplanNetDefinition* nd, GError** error)
+validate_backend_rules(const NetplanParser* npp, NetplanNetDefinition* nd, GError** error)
{
gboolean valid = FALSE;
/* Set a dummy, NULL yaml_node_t for error reporting */
@@ -364,7 +364,7 @@ validate_backend_rules(NetplanNetDefinition* nd, GError** error)
g_assert(nd->type != NETPLAN_DEF_TYPE_NONE);
if (nd->type == NETPLAN_DEF_TYPE_TUNNEL) {
- valid = validate_tunnel_backend_rules(nd, node, error);
+ valid = validate_tunnel_backend_rules(npp, nd, node, error);
if (!valid)
goto backend_rules_error;
}
@@ -437,7 +437,7 @@ check_defroute(struct _defroute_entry *candidate,
}
gboolean
-validate_default_route_consistency(GHashTable *netdefs, GError ** error)
+validate_default_route_consistency(const NetplanParser* npp, GHashTable *netdefs, GError ** error)
{
struct _defroute_entry candidate = {};
GSList *defroutes = NULL;
diff --git a/src/validation.h b/src/validation.h
index 18e98fe..e0a30f3 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -31,10 +31,10 @@ NETPLAN_ABI gboolean
is_wireguard_key(const char* hostname);
gboolean
-validate_netdef_grammar(NetplanNetDefinition* nd, yaml_node_t* node, GError** error);
+validate_netdef_grammar(const NetplanParser* npp, NetplanNetDefinition* nd, yaml_node_t* node, GError** error);
gboolean
-validate_backend_rules(NetplanNetDefinition* nd, GError** error);
+validate_backend_rules(const NetplanParser* npp, NetplanNetDefinition* nd, GError** error);
gboolean
-validate_default_route_consistency(GHashTable* netdefs, GError** error);
+validate_default_route_consistency(const NetplanParser* npp, GHashTable* netdefs, GError** error);
diff --git a/src/yaml-helpers.h b/src/yaml-helpers.h
index 6408ac1..55fc94c 100644
--- a/src/yaml-helpers.h
+++ b/src/yaml-helpers.h
@@ -22,33 +22,33 @@
#define YAML_MAPPING_OPEN(event_ptr, emitter_ptr) \
{ \
yaml_mapping_start_event_initialize(event_ptr, NULL, (yaml_char_t *)YAML_MAP_TAG, 1, YAML_BLOCK_MAPPING_STYLE); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
}
#define YAML_MAPPING_CLOSE(event_ptr, emitter_ptr) \
{ \
yaml_mapping_end_event_initialize(event_ptr); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
}
#define YAML_SEQUENCE_OPEN(event_ptr, emitter_ptr) \
{ \
yaml_sequence_start_event_initialize(event_ptr, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_BLOCK_SEQUENCE_STYLE); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
}
#define YAML_SEQUENCE_CLOSE(event_ptr, emitter_ptr) \
{ \
yaml_sequence_end_event_initialize(event_ptr); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
}
#define YAML_SCALAR_PLAIN(event_ptr, emitter_ptr, scalar) \
{ \
yaml_scalar_event_initialize(event_ptr, NULL, (yaml_char_t *)YAML_STR_TAG, (yaml_char_t *)scalar, strlen(scalar), 1, 0, YAML_PLAIN_SCALAR_STYLE); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
}
/* Implicit plain and quoted tags, double quoted style */
#define YAML_SCALAR_QUOTED(event_ptr, emitter_ptr, scalar) \
{ \
yaml_scalar_event_initialize(event_ptr, NULL, (yaml_char_t *)YAML_STR_TAG, (yaml_char_t *)scalar, strlen(scalar), 1, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
}
#define YAML_STRING(event_ptr, emitter_ptr, key, value_ptr) \
{ \
@@ -77,9 +77,9 @@
yaml_emitter_initialize(emitter_ptr); \
yaml_emitter_set_output_file(emitter_ptr, file); \
yaml_stream_start_event_initialize(event_ptr, YAML_UTF8_ENCODING); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
yaml_document_start_event_initialize(event_ptr, NULL, NULL, NULL, 1); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
YAML_MAPPING_OPEN(event_ptr, emitter_ptr); \
}
/* close initial YAML mapping, document, stream and emitter */
@@ -87,8 +87,8 @@
{ \
YAML_MAPPING_CLOSE(event_ptr, emitter_ptr); \
yaml_document_end_event_initialize(event_ptr, 1); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
yaml_stream_end_event_initialize(event_ptr); \
- if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \
+ if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto err_path; \
yaml_emitter_delete(emitter_ptr); \
}