From 467e88a2b01805a796169b8843fbf6d376606882 Mon Sep 17 00:00:00 2001 From: Simon Chopin <87005181+schopin-pro@users.noreply.github.com> Date: Thu, 30 Sep 2021 14:17:13 +0200 Subject: API/ABI: restrict the symbol export to a determined public API (#227) The goal of this PR is to properly determine what the public interface of libnetplan is. There is potentially a bit of ABI breakage, as symbols now default to hidden status unless explicitly marked otherwise, and said marking was done manually by looking at the current consumers I had on my system and trying to fill in the blanks. The API, on the other hand, has been conscientiously broken, as most of what was exposed in the headers are now safely hidden away in our internal headers. This is by design, and AFAICT should not break existing code. This PR depends on #230, as denoted by the merge commit in there. It should make independent review a bit easier :). Given the fact that the main purpose of this PR is to limit the amount of symbols we export, we can safely assume that strictly speaking, there is ABI breakage. However, the whole point was to only expose the symbols that are in actual use out there in the real world. As usual, the patchset has been edited expecting a review commit by commit, as the whole diff can be a bit daunting. COMMITS: * libnetplan: rework netplan,parse{-nm},util.h as public headers This work involves splitting out some things from those headers into new internal headers, and moving definitions around so that the public headers are as self-contained as possible. For the new internal headers, I decided to have a big "types.h" header containing all the types used in a network definition. In itself, these types aren't related to parsing except that the parser module is the only producer, so I decided they could live on their own. This is also the place where type-specific helpers can be found, such as reset_netdef(). The various macros used to generate YAML were gathered up from both source headers into a new yaml-helpers.h header, whereas the various global state definitions were split off into their own headers, making it easier to spot which areas of the code still rely on global state. The remainder functions were moved into util-internal.h This allows us to minimize the API exposed to the outside world. V2: * Remove the extraneous struct net_definition line, as it is redundant with the typedef * Normalize all the symbol declarations to have the symbol name at the beginning of their own line, at least in the headers we touched. V3: * Remove extraneous stdbool.h header * Split parse-helpers.h into yaml-helpers.h and util-internal.h * Add uuid as a dependency of the dbus generator to make it compile with the new lay of the land. * Add some missing copyright headers * libnetplan: Properly mark the lib/bin interface This patch cleanly marks which functions/objects are part of the public library API, and which are meant to be consumed by our own binaries. In order to reduce as much as possible the ABI dependencies between our binaries and the library, I move the various generator modules into the library as it make sense for them to access directly the objects. On the other hand, both generate.c and dbus.c should be relatively trivial to change to use getters and setters instead of direct structure access. Those changes will be the object of later patches. V3: * Makefile: consolidate the pkg-config calls and add back the LDFLAGS variable * Normalize the touched function declarations to always have the symbol name at the start of the line. * libnetplan: add back ABI compatibility Re-export (and recreate) various symbols that are needed by the `generate` binary as shipped in the Ubuntu package 0.103-0ubuntu5 I have chosen a separate marker for those, in order to distinguish what was exposed deliberately and by accident. That way, if we need to do a SONAME bump, we can clean up the symbols marked with NETPLAN_ABI. V3: * Normalize the declarations that are touched to always have the symbol name at the start of the line * libnetplan: export Python-used symbols as internal * libnetplan: hide all symbols by default Only those marked by NETPLAN_{PUBLIC,INTERNAL,ABI} will be available to the loader. --- Makefile | 28 ++- include/netplan.h | 29 +++ include/parse-nm.h | 26 +++ include/parse.h | 66 +++++++ include/util.h | 33 ++++ src/dbus.c | 2 +- src/error.c | 1 + src/generate.c | 2 + src/names.c | 4 +- src/names.h | 3 +- src/netdef.c | 316 ------------------------------- src/netplan.c | 6 +- src/netplan.h | 96 ---------- src/networkd.c | 2 + src/networkd.h | 17 +- src/nm.c | 3 + src/nm.h | 13 +- src/openvswitch.c | 2 + src/openvswitch.h | 13 +- src/parse-globals.h | 51 +++++ src/parse-nm.c | 1 + src/parse-nm.h | 22 --- src/parse.c | 14 +- src/parse.h | 521 ---------------------------------------------------- src/sriov.c | 3 +- src/sriov.h | 8 +- src/types.c | 317 ++++++++++++++++++++++++++++++++ src/types.h | 431 +++++++++++++++++++++++++++++++++++++++++++ src/util-internal.h | 70 +++++++ src/util.c | 10 +- src/util.h | 41 ----- src/validation.c | 6 +- src/validation.h | 5 +- src/yaml-helpers.h | 94 ++++++++++ 34 files changed, 1224 insertions(+), 1032 deletions(-) create mode 100644 include/netplan.h create mode 100644 include/parse-nm.h create mode 100644 include/parse.h create mode 100644 include/util.h delete mode 100644 src/netdef.c delete mode 100644 src/netplan.h create mode 100644 src/parse-globals.h delete mode 100644 src/parse-nm.h delete mode 100644 src/parse.h create mode 100644 src/types.c create mode 100644 src/types.h create mode 100644 src/util-internal.h delete mode 100644 src/util.h create mode 100644 src/yaml-helpers.h diff --git a/Makefile b/Makefile index 0c67710..ca3dea3 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,26 @@ BUILDFLAGS = \ -std=c99 \ -D_XOPEN_SOURCE=500 \ -DSBINDIR=\"$(SBINDIR)\" \ + -I${CURDIR}/include \ -Wall \ -Werror \ $(NULL) +SRCS = \ + src/error.c \ + src/names.c \ + src/netplan.c \ + src/networkd.c \ + src/nm.c \ + src/openvswitch.c \ + src/parse.c \ + src/parse-nm.c \ + src/sriov.c \ + src/types.c \ + src/util.c \ + src/validation.c \ + $(NULL) + SYSTEMD_GENERATOR_DIR=$(shell pkg-config --variable=systemdsystemgeneratordir systemd) SYSTEMD_UNIT_DIR=$(shell pkg-config --variable=systemdsystemunitdir systemd) BASH_COMPLETIONS_DIR=$(shell pkg-config --variable=completionsdir bash-completion || echo "/etc/bash_completion.d") @@ -38,15 +54,15 @@ default: netplan/_features.py generate netplan-dbus dbus/io.netplan.Netplan.serv %.o: src/%.c $(CC) $(BUILDFLAGS) $(CFLAGS) $(LDFLAGS) -c $^ `pkg-config --cflags --libs glib-2.0 gio-2.0 yaml-0.1 uuid` -libnetplan.so.$(NETPLAN_SOVER): parse.o netdef.o netplan.o util.o validation.o error.o parse-nm.o names.o - $(CC) -shared -Wl,-soname,libnetplan.so.$(NETPLAN_SOVER) $(BUILDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ `pkg-config --libs glib-2.0 gio-2.0 yaml-0.1` +libnetplan.so.$(NETPLAN_SOVER): $(SRCS) + $(CC) -shared -Wl,-soname,libnetplan.so.$(NETPLAN_SOVER) $(BUILDFLAGS) $(CFLAGS) -fvisibility=hidden $(LDFLAGS) -o $@ $^ `pkg-config --cflags --libs glib-2.0 gio-2.0 yaml-0.1 uuid` ln -snf libnetplan.so.$(NETPLAN_SOVER) libnetplan.so -generate: libnetplan.so.$(NETPLAN_SOVER) nm.o networkd.o openvswitch.o generate.o sriov.o names.o - $(CC) $(BUILDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ -L. -lnetplan `pkg-config --cflags --libs glib-2.0 gio-2.0 yaml-0.1 uuid` +generate: libnetplan.so.$(NETPLAN_SOVER) generate.o + $(CC) $(BUILDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(filter-out $<,$^) -L. -lnetplan `pkg-config --cflags --libs glib-2.0 gio-2.0 yaml-0.1 uuid` -netplan-dbus: src/dbus.c src/_features.h netdef.o parse.o util.o validation.o error.o names.o - $(CC) $(BUILDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(patsubst %.h,,$^) `pkg-config --cflags --libs libsystemd glib-2.0 gio-2.0 yaml-0.1` +netplan-dbus: libnetplan.so.$(NETPLAN_SOVER) src/_features.h dbus.o + $(CC) $(BUILDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(filter-out $<,$(patsubst %.h,,$^)) -L. -lnetplan `pkg-config --cflags --libs libsystemd glib-2.0 gio-2.0 yaml-0.1 uuid` src/_features.h: src/[^_]*.[hc] printf "#include \nstatic const char *feature_flags[] __attribute__((__unused__)) = {\n" > $@ diff --git a/include/netplan.h b/include/netplan.h new file mode 100644 index 0000000..9d30c26 --- /dev/null +++ b/include/netplan.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Canonical, Ltd. + * Author: Lukas Märdian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#define NETPLAN_PUBLIC __attribute__ ((visibility("default"))) +#define NETPLAN_INTERNAL __attribute__ ((visibility("default"))) +#define NETPLAN_ABI __attribute__ ((visibility("default"))) + +/** + * Represent a configuration stanza + */ +typedef struct net_definition NetplanNetDefinition; + +NETPLAN_PUBLIC void +write_netplan_conf(const NetplanNetDefinition* def, const char* rootdir); diff --git a/include/parse-nm.h b/include/parse-nm.h new file mode 100644 index 0000000..d83d665 --- /dev/null +++ b/include/parse-nm.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Canonical, Ltd. + * Author: Lukas Märdian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "netplan.h" +#include + +#define NETPLAN_NM_EMPTY_GROUP "_" + +NETPLAN_PUBLIC gboolean +netplan_parse_keyfile(const char* filename, GError** error); diff --git a/include/parse.h b/include/parse.h new file mode 100644 index 0000000..eda0260 --- /dev/null +++ b/include/parse.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 Canonical, Ltd. + * Author: Martin Pitt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include "netplan.h" +#include + +/**************************************************** + * Parsed definitions + ****************************************************/ + +typedef enum { + NETPLAN_DEF_TYPE_NONE, + /* physical devices */ + NETPLAN_DEF_TYPE_ETHERNET, + NETPLAN_DEF_TYPE_WIFI, + NETPLAN_DEF_TYPE_MODEM, + /* virtual devices */ + NETPLAN_DEF_TYPE_VIRTUAL, + NETPLAN_DEF_TYPE_BRIDGE = NETPLAN_DEF_TYPE_VIRTUAL, + NETPLAN_DEF_TYPE_BOND, + NETPLAN_DEF_TYPE_VLAN, + NETPLAN_DEF_TYPE_TUNNEL, + NETPLAN_DEF_TYPE_PORT, + /* Type fallback/passthrough */ + NETPLAN_DEF_TYPE_NM, + NETPLAN_DEF_TYPE_MAX_ +} NetplanDefType; + +typedef enum { + NETPLAN_BACKEND_NONE, + NETPLAN_BACKEND_NETWORKD, + NETPLAN_BACKEND_NM, + NETPLAN_BACKEND_OVS, + NETPLAN_BACKEND_MAX_, +} NetplanBackend; + +/**************************************************** + * Functions + ****************************************************/ + +NETPLAN_PUBLIC gboolean +netplan_parse_yaml(const char* filename, GError** error); + +NETPLAN_PUBLIC GHashTable* +netplan_finish_parse(GError** error); + +NETPLAN_PUBLIC guint +netplan_clear_netdefs(); + +NETPLAN_PUBLIC NetplanBackend +netplan_get_global_backend(); diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..e7e1a0f --- /dev/null +++ b/include/util.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 Canonical, Ltd. + * Author: Martin Pitt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include "netplan.h" + +NETPLAN_PUBLIC gboolean +netplan_delete_connection(const char* id, const char* rootdir); + +NETPLAN_PUBLIC gboolean +netplan_generate(const char* rootdir); + +NETPLAN_PUBLIC gchar* +netplan_get_id_from_nm_filename(const char* filename, const char* ssid); + +NETPLAN_PUBLIC gchar* +netplan_get_filename_by_id(const char* netdef_id, const char* rootdir); diff --git a/src/dbus.c b/src/dbus.c index a486b54..1442af3 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -15,7 +15,7 @@ #include #include "_features.h" -#include "util.h" +#include "util-internal.h" typedef struct { sd_bus_slot *slot; diff --git a/src/error.c b/src/error.c index 0c34e17..ff28be9 100644 --- a/src/error.c +++ b/src/error.c @@ -22,6 +22,7 @@ #include #include "parse.h" +#include "parse-globals.h" /**************************************************** diff --git a/src/generate.c b/src/generate.c index caff955..00c7035 100644 --- a/src/generate.c +++ b/src/generate.c @@ -27,7 +27,9 @@ #include #include "util.h" +#include "util-internal.h" #include "parse.h" +#include "parse-globals.h" #include "names.h" #include "networkd.h" #include "nm.h" diff --git a/src/names.c b/src/names.c index 378c6b4..3a085ba 100644 --- a/src/names.c +++ b/src/names.c @@ -107,8 +107,8 @@ NAME_FUNCTION(wifi_mode, NetplanWifiMode); /* ABI compatibility definitions */ -const char* +NETPLAN_ABI const char* tunnel_mode_to_string(NetplanTunnelMode val) __attribute__ ((alias ("netplan_tunnel_mode_name"))); -extern const char* +NETPLAN_ABI extern const char* netplan_backend_to_name __attribute__((alias("netplan_backend_to_str"))); diff --git a/src/names.h b/src/names.h index 256a600..c1b108b 100644 --- a/src/names.h +++ b/src/names.h @@ -18,8 +18,9 @@ #pragma once #include "netplan.h" +#include "types.h" -const char* +NETPLAN_INTERNAL const char* netplan_backend_name(NetplanBackend val); const char* diff --git a/src/netdef.c b/src/netdef.c deleted file mode 100644 index 36464f6..0000000 --- a/src/netdef.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2021 Canonical, Ltd. - * Author: Simon Chopin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* This module contains functions to deal with the NetplanNetDefinition objects. - * Notably, accessors and destructors. - */ - -#include -#include "parse.h" - -#define FREE_AND_NULLIFY(ptr) { g_free(ptr); ptr = NULL; } - -/* Helper function to free a GArray after applying a destructor to its - * elements. Note that in the most trivial case (g_free) we should probably - * have used a GPtrArray directly... */ -static void -free_garray_with_destructor(GArray** array, void (destructor)(void *)) -{ - if (*array) { - for (size_t i = 0; i < (*array)->len; ++i) { - void* ptr = g_array_index(*array, char*, i); - destructor(ptr); - } - g_array_free(*array, TRUE); - *array = NULL; - } -} - -/* Helper function to free a GHashTable after applying a simple destructor to its - * elements. */ -static void -free_hashtable_with_destructor(GHashTable** hash, void (destructor)(void *)) { - if (*hash) { - GHashTableIter iter; - gpointer key, value; - g_hash_table_iter_init(&iter, *hash); - while (g_hash_table_iter_next(&iter, &key, &value)) - destructor(value); - g_hash_table_destroy(*hash); - *hash = NULL; - } -} - -static void -free_address_options(void* ptr) -{ - NetplanAddressOptions* opts = ptr; - g_free(opts->address); - g_free(opts->label); - g_free(opts->lifetime); - g_free(opts); -} - -static void -free_route(void* ptr) -{ - NetplanIPRoute* route = ptr; - g_free(route->scope); - g_free(route->type); - g_free(route->to); - g_free(route->from); - g_free(route->via); - g_free(route); -} - -static void -free_ip_rules(void* ptr) -{ - NetplanIPRule* rule = ptr; - g_free(rule->to); - g_free(rule->from); - g_free(rule); -} - -static void -free_wireguard_peer(void* ptr) -{ - NetplanWireguardPeer* wg = ptr; - g_free(wg->endpoint); - g_free(wg->preshared_key); - g_free(wg->public_key); - free_garray_with_destructor(&wg->allowed_ips, g_free); - g_free(wg); -} - -static void -reset_auth_settings(NetplanAuthenticationSettings* auth) -{ - FREE_AND_NULLIFY(auth->identity); - FREE_AND_NULLIFY(auth->anonymous_identity); - FREE_AND_NULLIFY(auth->password); - FREE_AND_NULLIFY(auth->ca_certificate); - FREE_AND_NULLIFY(auth->client_certificate); - FREE_AND_NULLIFY(auth->client_key); - FREE_AND_NULLIFY(auth->client_key_password); - FREE_AND_NULLIFY(auth->phase2_auth); - auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_NONE; - auth->eap_method = NETPLAN_AUTH_EAP_NONE; -} - -static void -reset_ovs_settings(NetplanOVSSettings* settings) -{ - settings->mcast_snooping = FALSE; - settings->rstp = FALSE; - - free_hashtable_with_destructor(&settings->external_ids, g_free); - free_hashtable_with_destructor(&settings->other_config, g_free); - - FREE_AND_NULLIFY(settings->lacp); - FREE_AND_NULLIFY(settings->fail_mode); - - free_garray_with_destructor(&settings->protocols, g_free); - reset_auth_settings(&settings->ssl); - - free_garray_with_destructor(&settings->controller.addresses, g_free); - FREE_AND_NULLIFY(settings->controller.connection_mode); -} - -static void -reset_dhcp_overrides(NetplanDHCPOverrides* overrides) -{ - overrides->use_dns = TRUE; - FREE_AND_NULLIFY(overrides->use_domains); - overrides->use_ntp = TRUE; - overrides->send_hostname = TRUE; - overrides->use_hostname = TRUE; - overrides->use_mtu = TRUE; - overrides->use_routes = TRUE; - FREE_AND_NULLIFY(overrides->hostname); - overrides->metric = NETPLAN_METRIC_UNSPEC; -} - -/* Reset a backend settings object. The caller needs to specify the actual backend as it is not - * contained within the object itself! */ -static void -reset_backend_settings(NetplanBackendSettings* settings, NetplanBackend backend) -{ - switch (backend) { - case NETPLAN_BACKEND_NETWORKD: - FREE_AND_NULLIFY(settings->networkd.unit); - break; - case NETPLAN_BACKEND_NM: - FREE_AND_NULLIFY(settings->nm.name); - FREE_AND_NULLIFY(settings->nm.uuid); - FREE_AND_NULLIFY(settings->nm.stable_id); - FREE_AND_NULLIFY(settings->nm.device); - g_datalist_clear(&settings->nm.passthrough); - break; - default: - break; - } -} - -/* Free a heap-allocated NetplanWifiAccessPoint object. - * Signature made to match the g_hash_table_foreach function. - * @key: ignored - * @value: pointer to a heap-allocated NetlpanWifiAccessPoint object - * @data: pointer to a NetplanBackend value representing the renderer context in which - * to interpret the processed object, especially regarding the backend settings - */ -static void -free_access_point(void* key, void* value, void* data) -{ - NetplanWifiAccessPoint* ap = value; - g_free(ap->ssid); - g_free(ap->bssid); - reset_auth_settings(&ap->auth); - reset_backend_settings(&ap->backend_settings, *((NetplanBackend *)data)); - g_free(ap); -} - -/* Reset a given network definition to its initial state, releasing any owned data */ -void -reset_netdef(NetplanNetDefinition* netdef, NetplanDefType new_type, NetplanBackend new_backend) { - /* Needed for some cleanups down the line */ - NetplanBackend backend = netdef->backend; - - netdef->type = new_type; - netdef->backend = new_backend; - FREE_AND_NULLIFY(netdef->id); - memset(netdef->uuid, 0, sizeof(netdef->uuid)); - - netdef->optional = FALSE; - netdef->optional_addresses = 0; - netdef->critical = FALSE; - - netdef->dhcp4 = FALSE; - netdef->dhcp6 = FALSE; - - FREE_AND_NULLIFY(netdef->dhcp_identifier); - - reset_dhcp_overrides(&netdef->dhcp4_overrides); - reset_dhcp_overrides(&netdef->dhcp6_overrides); - netdef->accept_ra = NETPLAN_RA_MODE_KERNEL; - - free_garray_with_destructor(&netdef->ip4_addresses, g_free); - free_garray_with_destructor(&netdef->ip6_addresses, g_free); - free_garray_with_destructor(&netdef->address_options, free_address_options); - - netdef->ip6_privacy = FALSE; - netdef->ip6_addr_gen_mode = NETPLAN_ADDRGEN_DEFAULT; - FREE_AND_NULLIFY(netdef->ip6_addr_gen_token); - - FREE_AND_NULLIFY(netdef->gateway4); - FREE_AND_NULLIFY(netdef->gateway6); - free_garray_with_destructor(&netdef->ip4_nameservers, g_free); - free_garray_with_destructor(&netdef->ip6_nameservers, g_free); - free_garray_with_destructor(&netdef->search_domains, g_free); - free_garray_with_destructor(&netdef->routes, free_route); - free_garray_with_destructor(&netdef->ip_rules, free_ip_rules); - free_garray_with_destructor(&netdef->wireguard_peers, free_wireguard_peer); - - netdef->linklocal.ipv4 = FALSE; - netdef->linklocal.ipv6 = TRUE; - - FREE_AND_NULLIFY(netdef->bridge); - FREE_AND_NULLIFY(netdef->bond); - - FREE_AND_NULLIFY(netdef->peer); - - netdef->vlan_id = G_MAXUINT; /* 0 is a valid ID */ - netdef->vlan_link = NULL; - netdef->has_vlans = FALSE; - - FREE_AND_NULLIFY(netdef->set_mac); - netdef->mtubytes = 0; - netdef->ipv6_mtubytes = 0; - - FREE_AND_NULLIFY(netdef->set_name); - FREE_AND_NULLIFY(netdef->match.driver); - FREE_AND_NULLIFY(netdef->match.mac); - FREE_AND_NULLIFY(netdef->match.original_name); - netdef->has_match = FALSE; - netdef->wake_on_lan = FALSE; - netdef->wowlan = 0; - netdef->emit_lldp = FALSE; - - if (netdef->access_points) { - g_hash_table_foreach(netdef->access_points, free_access_point, &backend); - g_hash_table_destroy(netdef->access_points); - netdef->access_points = NULL; - } - - FREE_AND_NULLIFY(netdef->bond_params.mode); - FREE_AND_NULLIFY(netdef->bond_params.lacp_rate); - FREE_AND_NULLIFY(netdef->bond_params.monitor_interval); - FREE_AND_NULLIFY(netdef->bond_params.transmit_hash_policy); - FREE_AND_NULLIFY(netdef->bond_params.selection_logic); - FREE_AND_NULLIFY(netdef->bond_params.arp_interval); - free_garray_with_destructor(&netdef->bond_params.arp_ip_targets, g_free); - FREE_AND_NULLIFY(netdef->bond_params.arp_validate); - FREE_AND_NULLIFY(netdef->bond_params.arp_all_targets); - FREE_AND_NULLIFY(netdef->bond_params.up_delay); - FREE_AND_NULLIFY(netdef->bond_params.down_delay); - FREE_AND_NULLIFY(netdef->bond_params.fail_over_mac_policy); - FREE_AND_NULLIFY(netdef->bond_params.primary_reselect_policy); - FREE_AND_NULLIFY(netdef->bond_params.learn_interval); - FREE_AND_NULLIFY(netdef->bond_params.primary_slave); - memset(&netdef->bond_params, 0, sizeof(netdef->bond_params)); - - FREE_AND_NULLIFY(netdef->modem_params.apn); - FREE_AND_NULLIFY(netdef->modem_params.device_id); - FREE_AND_NULLIFY(netdef->modem_params.network_id); - FREE_AND_NULLIFY(netdef->modem_params.number); - FREE_AND_NULLIFY(netdef->modem_params.password); - FREE_AND_NULLIFY(netdef->modem_params.pin); - FREE_AND_NULLIFY(netdef->modem_params.sim_id); - FREE_AND_NULLIFY(netdef->modem_params.sim_operator_id); - FREE_AND_NULLIFY(netdef->modem_params.username); - memset(&netdef->modem_params, 0, sizeof(netdef->modem_params)); - - FREE_AND_NULLIFY(netdef->bridge_params.ageing_time); - FREE_AND_NULLIFY(netdef->bridge_params.forward_delay); - FREE_AND_NULLIFY(netdef->bridge_params.hello_time); - FREE_AND_NULLIFY(netdef->bridge_params.max_age); - memset(&netdef->bridge_params, 0, sizeof(netdef->bridge_params)); - netdef->custom_bridging = FALSE; - - FREE_AND_NULLIFY(netdef->tunnel.local_ip); - FREE_AND_NULLIFY(netdef->tunnel.remote_ip); - FREE_AND_NULLIFY(netdef->tunnel.input_key); - FREE_AND_NULLIFY(netdef->tunnel.output_key); - FREE_AND_NULLIFY(netdef->tunnel.private_key); - memset(&netdef->tunnel, 0, sizeof(netdef->tunnel)); - netdef->tunnel.mode = NETPLAN_TUNNEL_MODE_UNKNOWN; - - reset_auth_settings(&netdef->auth); - netdef->has_auth = FALSE; - - netdef->sriov_link = NULL; - netdef->sriov_vlan_filter = FALSE; - netdef->sriov_explicit_vf_count = G_MAXUINT; /* 0 is a valid number of VFs */ - - reset_ovs_settings(&netdef->ovs_settings); - reset_backend_settings(&netdef->backend_settings, backend); - - FREE_AND_NULLIFY(netdef->filename); - netdef->tunnel_ttl = 0; - FREE_AND_NULLIFY(netdef->activation_mode); - netdef->ignore_carrier = FALSE; -} diff --git a/src/netplan.c b/src/netplan.c index 7a7bc43..6285aa2 100644 --- a/src/netplan.c +++ b/src/netplan.c @@ -20,6 +20,8 @@ #include "netplan.h" #include "parse.h" +#include "parse-globals.h" +#include "yaml-helpers.h" #include "names.h" gchar *tmp = NULL; @@ -885,7 +887,7 @@ contains_netdef_type(gpointer key, gpointer value, gpointer user_data) * @rootdir: If not %NULL, generate configuration in this root directory * (useful for testing). */ -void +NETPLAN_INTERNAL void write_netplan_conf_full(const char* file_hint, const char* rootdir) { g_autofree gchar *path = NULL; @@ -980,7 +982,7 @@ void cleanup_netplan_conf(const char* rootdir) /** * Helper function for testing only */ -void +NETPLAN_INTERNAL void _write_netplan_conf(const char* netdef_id, const char* rootdir) { GHashTable* ht = NULL; diff --git a/src/netplan.h b/src/netplan.h deleted file mode 100644 index f8c09d1..0000000 --- a/src/netplan.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2021 Canonical, Ltd. - * Author: Lukas Märdian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "parse.h" - -#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; \ -} -#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; \ -} -#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; \ -} -#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; \ -} -#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; \ -} -/* 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; \ -} -#define YAML_STRING(event_ptr, emitter_ptr, key, value_ptr) \ -{ \ - if (value_ptr) { \ - YAML_SCALAR_PLAIN(event_ptr, emitter_ptr, key); \ - YAML_SCALAR_QUOTED(event_ptr, emitter_ptr, value_ptr); \ - } \ -} -#define YAML_STRING_PLAIN(event_ptr, emitter_ptr, key, value_ptr) \ -{ \ - if (value_ptr) { \ - YAML_SCALAR_PLAIN(event_ptr, emitter_ptr, key); \ - YAML_SCALAR_PLAIN(event_ptr, emitter_ptr, value_ptr); \ - } \ -} -#define YAML_UINT(event_ptr, emitter_ptr, key, value) \ -{ \ - tmp = g_strdup_printf("%u", value); \ - YAML_STRING_PLAIN(event_ptr, emitter_ptr, key, tmp); \ - g_free(tmp); \ -} - -/* open YAML emitter, document, stream and initial mapping */ -#define YAML_OUT_START(event_ptr, emitter_ptr, file) \ -{ \ - 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; \ - yaml_document_start_event_initialize(event_ptr, NULL, NULL, NULL, 1); \ - if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \ - YAML_MAPPING_OPEN(event_ptr, emitter_ptr); \ -} -/* close initial YAML mapping, document, stream and emitter */ -#define YAML_OUT_STOP(event_ptr, emitter_ptr) \ -{ \ - 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; \ - yaml_stream_end_event_initialize(event_ptr); \ - if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \ - yaml_emitter_delete(emitter_ptr); \ -} - -void write_netplan_conf(const NetplanNetDefinition* def, const char* rootdir); diff --git a/src/networkd.c b/src/networkd.c index e8e680e..f6c9ec9 100644 --- a/src/networkd.c +++ b/src/networkd.c @@ -27,8 +27,10 @@ #include "networkd.h" #include "parse.h" +#include "parse-globals.h" #include "names.h" #include "util.h" +#include "util-internal.h" #include "validation.h" /** diff --git a/src/networkd.h b/src/networkd.h index 41ab125..be2bb29 100644 --- a/src/networkd.h +++ b/src/networkd.h @@ -17,10 +17,17 @@ #pragma once -#include "parse.h" +#include "netplan.h" +#include -gboolean write_networkd_conf(const NetplanNetDefinition* def, const char* rootdir); -void cleanup_networkd_conf(const char* rootdir); -void enable_networkd(const char* generator_dir); +NETPLAN_INTERNAL gboolean +write_networkd_conf(const NetplanNetDefinition* def, const char* rootdir); -void write_network_file(const NetplanNetDefinition* def, const char* rootdir, const char* path); +NETPLAN_INTERNAL void +write_network_file(const NetplanNetDefinition* def, const char* rootdir, const char* path); + +NETPLAN_INTERNAL void +cleanup_networkd_conf(const char* rootdir); + +NETPLAN_INTERNAL void +enable_networkd(const char* generator_dir); diff --git a/src/nm.c b/src/nm.c index aef15ac..8e84a99 100644 --- a/src/nm.c +++ b/src/nm.c @@ -26,9 +26,12 @@ #include #include +#include "netplan.h" #include "nm.h" #include "parse.h" +#include "parse-globals.h" #include "util.h" +#include "util-internal.h" #include "validation.h" #include "parse-nm.h" diff --git a/src/nm.h b/src/nm.h index 9f8f9ca..ac86f00 100644 --- a/src/nm.h +++ b/src/nm.h @@ -17,8 +17,13 @@ #pragma once -#include "parse.h" +#include "netplan.h" -void write_nm_conf(NetplanNetDefinition* def, const char* rootdir); -void write_nm_conf_finish(const char* rootdir); -void cleanup_nm_conf(const char* rootdir); +NETPLAN_INTERNAL void +write_nm_conf(NetplanNetDefinition* def, const char* rootdir); + +NETPLAN_INTERNAL void +write_nm_conf_finish(const char* rootdir); + +NETPLAN_INTERNAL void +cleanup_nm_conf(const char* rootdir); diff --git a/src/openvswitch.c b/src/openvswitch.c index 2088fbe..3bf8631 100644 --- a/src/openvswitch.c +++ b/src/openvswitch.c @@ -25,7 +25,9 @@ #include "openvswitch.h" #include "networkd.h" #include "parse.h" +#include "parse-globals.h" #include "util.h" +#include "util-internal.h" static void write_ovs_systemd_unit(const char* id, const GString* cmds, const char* rootdir, gboolean physical, gboolean cleanup, const char* dependency) diff --git a/src/openvswitch.h b/src/openvswitch.h index 69bd6ee..7abea4d 100644 --- a/src/openvswitch.h +++ b/src/openvswitch.h @@ -17,8 +17,13 @@ #pragma once -#include "parse.h" +#include "netplan.h" -void write_ovs_conf(const NetplanNetDefinition* def, const char* rootdir); -void write_ovs_conf_finish(const char* rootdir); -void cleanup_ovs_conf(const char* rootdir); +NETPLAN_INTERNAL void +write_ovs_conf(const NetplanNetDefinition* def, const char* rootdir); + +NETPLAN_INTERNAL void +write_ovs_conf_finish(const char* rootdir); + +NETPLAN_INTERNAL void +cleanup_ovs_conf(const char* rootdir); diff --git a/src/parse-globals.h b/src/parse-globals.h new file mode 100644 index 0000000..a7b2be8 --- /dev/null +++ b/src/parse-globals.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 Canonical, Ltd. + * Author: Simon Chopin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#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, + * we consider that only netdefs_ordered is owner of this data. One should not + * free() objects obtained from netdefs, and proper care should be taken to remove + * any reference of an object in netdefs when destroying it from netdefs_ordered. + */ +extern GHashTable* +netdefs; + +extern GList* +netdefs_ordered; + +extern NetplanOVSSettings +ovs_settings_global; diff --git a/src/parse-nm.c b/src/parse-nm.c index bb83bf5..9d5d9cf 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 "util-internal.h" /** * NetworkManager writes the alias for '802-3-ethernet' (ethernet), diff --git a/src/parse-nm.h b/src/parse-nm.h deleted file mode 100644 index 53973f7..0000000 --- a/src/parse-nm.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2021 Canonical, Ltd. - * Author: Lukas Märdian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#define NETPLAN_NM_EMPTY_GROUP "_" - -gboolean netplan_parse_keyfile(const char* filename, GError** error); diff --git a/src/parse.c b/src/parse.c index f62deef..55ead8f 100644 --- a/src/parse.c +++ b/src/parse.c @@ -28,11 +28,14 @@ #include #include "parse.h" -#include "util.h" #include "names.h" +#include "util-internal.h" #include "error.h" #include "validation.h" +#define NETPLAN_VERSION_MIN 2 +#define NETPLAN_VERSION_MAX 3 + /* convenience macro to put the offset of a NetplanNetDefinition field into "void* data" */ #define access_point_offset(field) GUINT_TO_POINTER(offsetof(NetplanWifiAccessPoint, field)) #define addr_option_offset(field) GUINT_TO_POINTER(offsetof(NetplanAddressOptions, field)) @@ -73,12 +76,15 @@ const char* cur_filename; static NetplanBackend backend_global, backend_cur_type; /* global OpenVSwitch settings */ +NETPLAN_INTERNAL NetplanOVSSettings ovs_settings_global; /* Global ID → NetplanNetDefinition* map for all parsed config files */ +NETPLAN_INTERNAL GHashTable* netdefs; /* Contains the same objects as 'netdefs' but ordered by dependency */ +NETPLAN_INTERNAL GList* netdefs_ordered; /* Set of IDs in currently parsed YAML file, for being able to detect @@ -900,7 +906,8 @@ handle_match(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** er return process_mapping(doc, node, match_handlers, NULL, error); } -struct NetplanWifiWowlanType NETPLAN_WIFI_WOWLAN_TYPES[] = { +NETPLAN_ABI struct NetplanWifiWowlanType +NETPLAN_WIFI_WOWLAN_TYPES[] = { {"default", NETPLAN_WIFI_WOWLAN_DEFAULT}, {"any", NETPLAN_WIFI_WOWLAN_ANY}, {"disconnect", NETPLAN_WIFI_WOWLAN_DISCONNECT}, @@ -1311,7 +1318,8 @@ handle_link_local(yaml_document_t* doc, yaml_node_t* node, const void* _, GError return TRUE; } -struct NetplanOptionalAddressType NETPLAN_OPTIONAL_ADDRESS_TYPES[] = { +NETPLAN_ABI struct NetplanOptionalAddressType +NETPLAN_OPTIONAL_ADDRESS_TYPES[] = { {"ipv4-ll", NETPLAN_OPTIONAL_IPV4_LL}, {"ipv6-ra", NETPLAN_OPTIONAL_IPV6_RA}, {"dhcp4", NETPLAN_OPTIONAL_DHCP4}, diff --git a/src/parse.h b/src/parse.h deleted file mode 100644 index 28050f2..0000000 --- a/src/parse.h +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright (C) 2016 Canonical, Ltd. - * Author: Martin Pitt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include - -#define NETPLAN_VERSION_MIN 2 -#define NETPLAN_VERSION_MAX 3 - - -/* 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; - -/**************************************************** - * Parsed definitions - ****************************************************/ - -typedef enum { - NETPLAN_DEF_TYPE_NONE, - /* physical devices */ - NETPLAN_DEF_TYPE_ETHERNET, - NETPLAN_DEF_TYPE_WIFI, - NETPLAN_DEF_TYPE_MODEM, - /* virtual devices */ - NETPLAN_DEF_TYPE_VIRTUAL, - NETPLAN_DEF_TYPE_BRIDGE = NETPLAN_DEF_TYPE_VIRTUAL, - NETPLAN_DEF_TYPE_BOND, - NETPLAN_DEF_TYPE_VLAN, - NETPLAN_DEF_TYPE_TUNNEL, - NETPLAN_DEF_TYPE_PORT, - /* Type fallback/passthrough */ - NETPLAN_DEF_TYPE_NM, - NETPLAN_DEF_TYPE_MAX_ -} NetplanDefType; - -typedef enum { - NETPLAN_BACKEND_NONE, - NETPLAN_BACKEND_NETWORKD, - NETPLAN_BACKEND_NM, - NETPLAN_BACKEND_OVS, - NETPLAN_BACKEND_MAX_, -} NetplanBackend; - -typedef enum { - NETPLAN_RA_MODE_KERNEL, - NETPLAN_RA_MODE_ENABLED, - NETPLAN_RA_MODE_DISABLED, -} NetplanRAMode; - -typedef enum { - NETPLAN_OPTIONAL_IPV4_LL = 1<<0, - NETPLAN_OPTIONAL_IPV6_RA = 1<<1, - NETPLAN_OPTIONAL_DHCP4 = 1<<2, - NETPLAN_OPTIONAL_DHCP6 = 1<<3, - NETPLAN_OPTIONAL_STATIC = 1<<4, -} NetplanOptionalAddressFlag; - -typedef enum { - NETPLAN_ADDRGEN_DEFAULT, - NETPLAN_ADDRGEN_EUI64, - NETPLAN_ADDRGEN_STABLEPRIVACY, - NETPLAN_ADDRGEN_MAX, -} NetplanAddrGenMode; - -struct NetplanOptionalAddressType { - char* name; - NetplanOptionalAddressFlag flag; -}; - -extern struct NetplanOptionalAddressType NETPLAN_OPTIONAL_ADDRESS_TYPES[]; - -/* Tunnel mode enum; sync with NetworkManager's DBUS API */ -/* TODO: figure out whether networkd's GRETAP and NM's ISATAP - * are the same thing. - */ -typedef enum { - NETPLAN_TUNNEL_MODE_UNKNOWN = 0, - NETPLAN_TUNNEL_MODE_IPIP = 1, - NETPLAN_TUNNEL_MODE_GRE = 2, - NETPLAN_TUNNEL_MODE_SIT = 3, - NETPLAN_TUNNEL_MODE_ISATAP = 4, // NM only. - NETPLAN_TUNNEL_MODE_VTI = 5, - NETPLAN_TUNNEL_MODE_IP6IP6 = 6, - NETPLAN_TUNNEL_MODE_IPIP6 = 7, - NETPLAN_TUNNEL_MODE_IP6GRE = 8, - NETPLAN_TUNNEL_MODE_VTI6 = 9, - - /* systemd-only, apparently? */ - NETPLAN_TUNNEL_MODE_GRETAP = 101, - NETPLAN_TUNNEL_MODE_IP6GRETAP = 102, - NETPLAN_TUNNEL_MODE_WIREGUARD = 103, - - NETPLAN_TUNNEL_MODE_MAX_, -} NetplanTunnelMode; - -static const char* const -netplan_tunnel_mode_table[NETPLAN_TUNNEL_MODE_MAX_] = { - [NETPLAN_TUNNEL_MODE_UNKNOWN] = "unknown", - [NETPLAN_TUNNEL_MODE_IPIP] = "ipip", - [NETPLAN_TUNNEL_MODE_GRE] = "gre", - [NETPLAN_TUNNEL_MODE_SIT] = "sit", - [NETPLAN_TUNNEL_MODE_ISATAP] = "isatap", - [NETPLAN_TUNNEL_MODE_VTI] = "vti", - [NETPLAN_TUNNEL_MODE_IP6IP6] = "ip6ip6", - [NETPLAN_TUNNEL_MODE_IPIP6] = "ipip6", - [NETPLAN_TUNNEL_MODE_IP6GRE] = "ip6gre", - [NETPLAN_TUNNEL_MODE_VTI6] = "vti6", - - [NETPLAN_TUNNEL_MODE_GRETAP] = "gretap", - [NETPLAN_TUNNEL_MODE_IP6GRETAP] = "ip6gretap", - [NETPLAN_TUNNEL_MODE_WIREGUARD] = "wireguard", -}; - -typedef enum { - NETPLAN_WIFI_WOWLAN_DEFAULT = 1<<0, - NETPLAN_WIFI_WOWLAN_ANY = 1<<1, - NETPLAN_WIFI_WOWLAN_DISCONNECT = 1<<2, - NETPLAN_WIFI_WOWLAN_MAGIC = 1<<3, - NETPLAN_WIFI_WOWLAN_GTK_REKEY_FAILURE = 1<<4, - NETPLAN_WIFI_WOWLAN_EAP_IDENTITY_REQ = 1<<5, - NETPLAN_WIFI_WOWLAN_4WAY_HANDSHAKE = 1<<6, - NETPLAN_WIFI_WOWLAN_RFKILL_RELEASE = 1<<7, - NETPLAN_WIFI_WOWLAN_TCP = 1<<8, -} NetplanWifiWowlanFlag; - -struct NetplanWifiWowlanType { - char* name; - NetplanWifiWowlanFlag flag; -}; - -extern struct NetplanWifiWowlanType NETPLAN_WIFI_WOWLAN_TYPES[]; - -typedef enum { - NETPLAN_AUTH_KEY_MANAGEMENT_NONE, - NETPLAN_AUTH_KEY_MANAGEMENT_WPA_PSK, - NETPLAN_AUTH_KEY_MANAGEMENT_WPA_EAP, - NETPLAN_AUTH_KEY_MANAGEMENT_8021X, - NETPLAN_AUTH_KEY_MANAGEMENT_MAX, -} NetplanAuthKeyManagementType; - -typedef enum { - NETPLAN_AUTH_EAP_NONE, - NETPLAN_AUTH_EAP_TLS, - NETPLAN_AUTH_EAP_PEAP, - NETPLAN_AUTH_EAP_TTLS, - NETPLAN_AUTH_EAP_METHOD_MAX, -} NetplanAuthEAPMethod; - -typedef struct missing_node { - char* netdef_id; - const yaml_node_t* node; -} NetplanMissingNode; - -typedef struct authentication_settings { - NetplanAuthKeyManagementType key_management; - NetplanAuthEAPMethod eap_method; - char* identity; - char* anonymous_identity; - char* password; - char* ca_certificate; - char* client_certificate; - char* client_key; - char* client_key_password; - char* phase2_auth; /* netplan-feature: auth-phase2 */ -} NetplanAuthenticationSettings; - -/* Fields below are valid for dhcp4 and dhcp6 unless otherwise noted. */ -typedef struct dhcp_overrides { - gboolean use_dns; - gboolean use_ntp; - gboolean send_hostname; - gboolean use_hostname; - gboolean use_mtu; - gboolean use_routes; - char* use_domains; /* netplan-feature: dhcp-use-domains */ - char* hostname; - guint metric; -} NetplanDHCPOverrides; - -typedef struct ovs_controller { - char* connection_mode; - GArray* addresses; -} NetplanOVSController; - -typedef struct ovs_settings { - GHashTable* external_ids; - GHashTable* other_config; - char* lacp; - char* fail_mode; - gboolean mcast_snooping; - GArray* protocols; - gboolean rstp; - NetplanOVSController controller; - NetplanAuthenticationSettings ssl; -} NetplanOVSSettings; - -typedef union { - struct NetplanNMSettings { - char *name; - char *uuid; - char *stable_id; - char *device; - GData* passthrough; /* See g_datalist* functions */ - } nm; - struct NetplanNetworkdSettings { - char *unit; - } networkd; -} NetplanBackendSettings; - -/** - * Represent a configuration stanza - */ - -struct net_definition; - -typedef struct net_definition NetplanNetDefinition; - -struct net_definition { - NetplanDefType type; - NetplanBackend backend; - char* id; - /* only necessary for NetworkManager connection UUIDs in some cases */ - uuid_t uuid; - - /* status options */ - gboolean optional; - NetplanOptionalAddressFlag optional_addresses; - gboolean critical; - - /* addresses */ - gboolean dhcp4; - gboolean dhcp6; - char* dhcp_identifier; - NetplanDHCPOverrides dhcp4_overrides; - NetplanDHCPOverrides dhcp6_overrides; - NetplanRAMode accept_ra; - GArray* ip4_addresses; - GArray* ip6_addresses; - GArray* address_options; - gboolean ip6_privacy; - guint ip6_addr_gen_mode; - char* ip6_addr_gen_token; - char* gateway4; - char* gateway6; - GArray* ip4_nameservers; - GArray* ip6_nameservers; - GArray* search_domains; - GArray* routes; - GArray* ip_rules; - GArray* wireguard_peers; - struct { - gboolean ipv4; - gboolean ipv6; - } linklocal; - - /* master ID for slave devices */ - char* bridge; - char* bond; - - /* peer ID for OVS patch ports */ - char* peer; - - /* vlan */ - guint vlan_id; - NetplanNetDefinition* vlan_link; - gboolean has_vlans; - - /* Configured custom MAC address */ - char* set_mac; - - /* interface mtu */ - guint mtubytes; - /* ipv6 mtu */ - /* netplan-feature: ipv6-mtu */ - guint ipv6_mtubytes; - - /* these properties are only valid for physical interfaces (type < ND_VIRTUAL) */ - char* set_name; - struct { - char* driver; - char* mac; - char* original_name; - } match; - gboolean has_match; - gboolean wake_on_lan; - NetplanWifiWowlanFlag wowlan; - gboolean emit_lldp; - - /* these properties are only valid for NETPLAN_DEF_TYPE_WIFI */ - GHashTable* access_points; /* SSID → NetplanWifiAccessPoint* */ - - struct { - char* mode; - char* lacp_rate; - char* monitor_interval; - guint min_links; - char* transmit_hash_policy; - char* selection_logic; - gboolean all_slaves_active; - char* arp_interval; - GArray* arp_ip_targets; - char* arp_validate; - char* arp_all_targets; - char* up_delay; - char* down_delay; - char* fail_over_mac_policy; - guint gratuitous_arp; - /* TODO: unsolicited_na */ - guint packets_per_slave; - char* primary_reselect_policy; - guint resend_igmp; - char* learn_interval; - char* primary_slave; - } bond_params; - - /* netplan-feature: modems */ - struct { - char* apn; - gboolean auto_config; - char* device_id; - char* network_id; - char* number; - char* password; - char* pin; - char* sim_id; - char* sim_operator_id; - char* username; - } modem_params; - - struct { - char* ageing_time; - guint priority; - guint port_priority; - char* forward_delay; - char* hello_time; - char* max_age; - guint path_cost; - gboolean stp; - } bridge_params; - gboolean custom_bridging; - - struct { - NetplanTunnelMode mode; - char *local_ip; - char *remote_ip; - char *input_key; - char *output_key; - char *private_key; /* used for wireguard */ - guint fwmark; - guint port; - } tunnel; - - NetplanAuthenticationSettings auth; - gboolean has_auth; - - /* these properties are only valid for SR-IOV NICs */ - /* netplan-feature: sriov */ - struct net_definition* sriov_link; - gboolean sriov_vlan_filter; - guint sriov_explicit_vf_count; - - /* these properties are only valid for OpenVSwitch */ - /* netplan-feature: openvswitch */ - NetplanOVSSettings ovs_settings; - - NetplanBackendSettings backend_settings; - - char* filename; - /* it cannot be in the tunnel struct: https://github.com/canonical/netplan/pull/206 */ - guint tunnel_ttl; - - /* netplan-feature: activation-mode */ - char* activation_mode; - - /* configure without carrier */ - gboolean ignore_carrier; - - /* offload options */ - gboolean receive_checksum_offload; - gboolean transmit_checksum_offload; - gboolean tcp_segmentation_offload; - gboolean tcp6_segmentation_offload; - gboolean generic_segmentation_offload; - gboolean generic_receive_offload; - gboolean large_receive_offload; -}; - -typedef enum { - NETPLAN_WIFI_MODE_INFRASTRUCTURE, - NETPLAN_WIFI_MODE_ADHOC, - NETPLAN_WIFI_MODE_AP, - NETPLAN_WIFI_MODE_OTHER, - NETPLAN_WIFI_MODE_MAX_ -} NetplanWifiMode; - -typedef struct { - char *endpoint; - char *public_key; - char *preshared_key; - GArray *allowed_ips; - guint keepalive; -} NetplanWireguardPeer; - -typedef enum { - NETPLAN_WIFI_BAND_DEFAULT, - NETPLAN_WIFI_BAND_5, - NETPLAN_WIFI_BAND_24 -} NetplanWifiBand; - -typedef struct { - char* address; - char* lifetime; - char* label; -} NetplanAddressOptions; - -typedef struct { - NetplanWifiMode mode; - char* ssid; - NetplanWifiBand band; - char* bssid; - gboolean hidden; - guint channel; - - NetplanAuthenticationSettings auth; - gboolean has_auth; - - NetplanBackendSettings backend_settings; -} NetplanWifiAccessPoint; - -#define NETPLAN_ADVERTISED_RECEIVE_WINDOW_UNSPEC 0 -#define NETPLAN_CONGESTION_WINDOW_UNSPEC 0 -#define NETPLAN_MTU_UNSPEC 0 -#define NETPLAN_METRIC_UNSPEC G_MAXUINT -#define NETPLAN_ROUTE_TABLE_UNSPEC 0 -#define NETPLAN_IP_RULE_PRIO_UNSPEC G_MAXUINT -#define NETPLAN_IP_RULE_FW_MARK_UNSPEC 0 -#define NETPLAN_IP_RULE_TOS_UNSPEC G_MAXUINT - -typedef struct { - guint family; - char* type; - char* scope; - guint table; - - char* from; - char* to; - char* via; - - gboolean onlink; - - /* valid metrics are valid positive integers. - * invalid metrics are represented by METRIC_UNSPEC */ - guint metric; - - guint mtubytes; - guint congestion_window; - guint advertised_receive_window; -} NetplanIPRoute; - -typedef struct { - guint family; - - char* from; - char* to; - - /* table: Valid values are 1 <= x <= 4294967295) */ - guint table; - guint priority; - /* fwmark: Valid values are 1 <= x <= 4294967295) */ - guint fwmark; - /* type-of-service: between 0 and 255 */ - guint tos; -} NetplanIPRule; - -/* Written/updated by parse_yaml(): char* id → net_definition. - * - * Since both netdefs and netdefs_ordered store pointers to the same elements, - * we consider that only netdefs_ordered is owner of this data. One should not - * free() objects obtained from netdefs, and proper care should be taken to remove - * any reference of an object in netdefs when destroying it from netdefs_ordered. - */ -extern GHashTable* netdefs; -extern GList* netdefs_ordered; -extern NetplanOVSSettings ovs_settings_global; - -/**************************************************** - * Functions - ****************************************************/ - -gboolean netplan_parse_yaml(const char* filename, GError** error); -GHashTable* netplan_finish_parse(GError** error); -guint netplan_clear_netdefs(); -NetplanBackend netplan_get_global_backend(); -NetplanNetDefinition* netplan_netdef_new(const char* id, NetplanDefType type, NetplanBackend renderer); -void reset_netdef(NetplanNetDefinition *netdef, NetplanDefType type, NetplanBackend renderer); - -void process_input_file(const char* f); -gboolean process_yaml_hierarchy(const char* rootdir); diff --git a/src/sriov.c b/src/sriov.c index 60f9800..906aac2 100644 --- a/src/sriov.c +++ b/src/sriov.c @@ -21,7 +21,8 @@ #include #include -#include "util.h" +#include "util-internal.h" +#include "sriov.h" void write_sriov_conf_finish(const char* rootdir) diff --git a/src/sriov.h b/src/sriov.h index 7cd5896..e71f573 100644 --- a/src/sriov.h +++ b/src/sriov.h @@ -16,6 +16,10 @@ */ #pragma once +#include "netplan.h" -void write_sriov_conf_finish(const char* rootdir); -void cleanup_sriov_conf(const char* rootdir); +NETPLAN_INTERNAL void +write_sriov_conf_finish(const char* rootdir); + +NETPLAN_INTERNAL void +cleanup_sriov_conf(const char* rootdir); diff --git a/src/types.c b/src/types.c new file mode 100644 index 0000000..b723f15 --- /dev/null +++ b/src/types.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2021 Canonical, Ltd. + * Author: Simon Chopin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* This module contains functions to deal with the Netplan objects, + * notably, accessors and destructors. Note that types specific to parsing + * are implemented separately. + */ + +#include +#include "types.h" + +#define FREE_AND_NULLIFY(ptr) { g_free(ptr); ptr = NULL; } + +/* Helper function to free a GArray after applying a destructor to its + * elements. Note that in the most trivial case (g_free) we should probably + * have used a GPtrArray directly... */ +static void +free_garray_with_destructor(GArray** array, void (destructor)(void *)) +{ + if (*array) { + for (size_t i = 0; i < (*array)->len; ++i) { + void* ptr = g_array_index(*array, char*, i); + destructor(ptr); + } + g_array_free(*array, TRUE); + *array = NULL; + } +} + +/* Helper function to free a GHashTable after applying a simple destructor to its + * elements. */ +static void +free_hashtable_with_destructor(GHashTable** hash, void (destructor)(void *)) { + if (*hash) { + GHashTableIter iter; + gpointer key, value; + g_hash_table_iter_init(&iter, *hash); + while (g_hash_table_iter_next(&iter, &key, &value)) + destructor(value); + g_hash_table_destroy(*hash); + *hash = NULL; + } +} + +static void +free_address_options(void* ptr) +{ + NetplanAddressOptions* opts = ptr; + g_free(opts->address); + g_free(opts->label); + g_free(opts->lifetime); + g_free(opts); +} + +static void +free_route(void* ptr) +{ + NetplanIPRoute* route = ptr; + g_free(route->scope); + g_free(route->type); + g_free(route->to); + g_free(route->from); + g_free(route->via); + g_free(route); +} + +static void +free_ip_rules(void* ptr) +{ + NetplanIPRule* rule = ptr; + g_free(rule->to); + g_free(rule->from); + g_free(rule); +} + +static void +free_wireguard_peer(void* ptr) +{ + NetplanWireguardPeer* wg = ptr; + g_free(wg->endpoint); + g_free(wg->preshared_key); + g_free(wg->public_key); + free_garray_with_destructor(&wg->allowed_ips, g_free); + g_free(wg); +} + +static void +reset_auth_settings(NetplanAuthenticationSettings* auth) +{ + FREE_AND_NULLIFY(auth->identity); + FREE_AND_NULLIFY(auth->anonymous_identity); + FREE_AND_NULLIFY(auth->password); + FREE_AND_NULLIFY(auth->ca_certificate); + FREE_AND_NULLIFY(auth->client_certificate); + FREE_AND_NULLIFY(auth->client_key); + FREE_AND_NULLIFY(auth->client_key_password); + FREE_AND_NULLIFY(auth->phase2_auth); + auth->key_management = NETPLAN_AUTH_KEY_MANAGEMENT_NONE; + auth->eap_method = NETPLAN_AUTH_EAP_NONE; +} + +static void +reset_ovs_settings(NetplanOVSSettings* settings) +{ + settings->mcast_snooping = FALSE; + settings->rstp = FALSE; + + free_hashtable_with_destructor(&settings->external_ids, g_free); + free_hashtable_with_destructor(&settings->other_config, g_free); + + FREE_AND_NULLIFY(settings->lacp); + FREE_AND_NULLIFY(settings->fail_mode); + + free_garray_with_destructor(&settings->protocols, g_free); + reset_auth_settings(&settings->ssl); + + free_garray_with_destructor(&settings->controller.addresses, g_free); + FREE_AND_NULLIFY(settings->controller.connection_mode); +} + +static void +reset_dhcp_overrides(NetplanDHCPOverrides* overrides) +{ + overrides->use_dns = TRUE; + FREE_AND_NULLIFY(overrides->use_domains); + overrides->use_ntp = TRUE; + overrides->send_hostname = TRUE; + overrides->use_hostname = TRUE; + overrides->use_mtu = TRUE; + overrides->use_routes = TRUE; + FREE_AND_NULLIFY(overrides->hostname); + overrides->metric = NETPLAN_METRIC_UNSPEC; +} + +/* Reset a backend settings object. The caller needs to specify the actual backend as it is not + * contained within the object itself! */ +static void +reset_backend_settings(NetplanBackendSettings* settings, NetplanBackend backend) +{ + switch (backend) { + case NETPLAN_BACKEND_NETWORKD: + FREE_AND_NULLIFY(settings->networkd.unit); + break; + case NETPLAN_BACKEND_NM: + FREE_AND_NULLIFY(settings->nm.name); + FREE_AND_NULLIFY(settings->nm.uuid); + FREE_AND_NULLIFY(settings->nm.stable_id); + FREE_AND_NULLIFY(settings->nm.device); + g_datalist_clear(&settings->nm.passthrough); + break; + default: + break; + } +} + +/* Free a heap-allocated NetplanWifiAccessPoint object. + * Signature made to match the g_hash_table_foreach function. + * @key: ignored + * @value: pointer to a heap-allocated NetlpanWifiAccessPoint object + * @data: pointer to a NetplanBackend value representing the renderer context in which + * to interpret the processed object, especially regarding the backend settings + */ +static void +free_access_point(void* key, void* value, void* data) +{ + NetplanWifiAccessPoint* ap = value; + g_free(ap->ssid); + g_free(ap->bssid); + reset_auth_settings(&ap->auth); + reset_backend_settings(&ap->backend_settings, *((NetplanBackend *)data)); + g_free(ap); +} + +/* Reset a given network definition to its initial state, releasing any owned data */ +void +reset_netdef(NetplanNetDefinition* netdef, NetplanDefType new_type, NetplanBackend new_backend) { + /* Needed for some cleanups down the line */ + NetplanBackend backend = netdef->backend; + + netdef->type = new_type; + netdef->backend = new_backend; + FREE_AND_NULLIFY(netdef->id); + memset(netdef->uuid, 0, sizeof(netdef->uuid)); + + netdef->optional = FALSE; + netdef->optional_addresses = 0; + netdef->critical = FALSE; + + netdef->dhcp4 = FALSE; + netdef->dhcp6 = FALSE; + + FREE_AND_NULLIFY(netdef->dhcp_identifier); + + reset_dhcp_overrides(&netdef->dhcp4_overrides); + reset_dhcp_overrides(&netdef->dhcp6_overrides); + netdef->accept_ra = NETPLAN_RA_MODE_KERNEL; + + free_garray_with_destructor(&netdef->ip4_addresses, g_free); + free_garray_with_destructor(&netdef->ip6_addresses, g_free); + free_garray_with_destructor(&netdef->address_options, free_address_options); + + netdef->ip6_privacy = FALSE; + netdef->ip6_addr_gen_mode = NETPLAN_ADDRGEN_DEFAULT; + FREE_AND_NULLIFY(netdef->ip6_addr_gen_token); + + FREE_AND_NULLIFY(netdef->gateway4); + FREE_AND_NULLIFY(netdef->gateway6); + free_garray_with_destructor(&netdef->ip4_nameservers, g_free); + free_garray_with_destructor(&netdef->ip6_nameservers, g_free); + free_garray_with_destructor(&netdef->search_domains, g_free); + free_garray_with_destructor(&netdef->routes, free_route); + free_garray_with_destructor(&netdef->ip_rules, free_ip_rules); + free_garray_with_destructor(&netdef->wireguard_peers, free_wireguard_peer); + + netdef->linklocal.ipv4 = FALSE; + netdef->linklocal.ipv6 = TRUE; + + FREE_AND_NULLIFY(netdef->bridge); + FREE_AND_NULLIFY(netdef->bond); + + FREE_AND_NULLIFY(netdef->peer); + + netdef->vlan_id = G_MAXUINT; /* 0 is a valid ID */ + netdef->vlan_link = NULL; + netdef->has_vlans = FALSE; + + FREE_AND_NULLIFY(netdef->set_mac); + netdef->mtubytes = 0; + netdef->ipv6_mtubytes = 0; + + FREE_AND_NULLIFY(netdef->set_name); + FREE_AND_NULLIFY(netdef->match.driver); + FREE_AND_NULLIFY(netdef->match.mac); + FREE_AND_NULLIFY(netdef->match.original_name); + netdef->has_match = FALSE; + netdef->wake_on_lan = FALSE; + netdef->wowlan = 0; + netdef->emit_lldp = FALSE; + + if (netdef->access_points) { + g_hash_table_foreach(netdef->access_points, free_access_point, &backend); + g_hash_table_destroy(netdef->access_points); + netdef->access_points = NULL; + } + + FREE_AND_NULLIFY(netdef->bond_params.mode); + FREE_AND_NULLIFY(netdef->bond_params.lacp_rate); + FREE_AND_NULLIFY(netdef->bond_params.monitor_interval); + FREE_AND_NULLIFY(netdef->bond_params.transmit_hash_policy); + FREE_AND_NULLIFY(netdef->bond_params.selection_logic); + FREE_AND_NULLIFY(netdef->bond_params.arp_interval); + free_garray_with_destructor(&netdef->bond_params.arp_ip_targets, g_free); + FREE_AND_NULLIFY(netdef->bond_params.arp_validate); + FREE_AND_NULLIFY(netdef->bond_params.arp_all_targets); + FREE_AND_NULLIFY(netdef->bond_params.up_delay); + FREE_AND_NULLIFY(netdef->bond_params.down_delay); + FREE_AND_NULLIFY(netdef->bond_params.fail_over_mac_policy); + FREE_AND_NULLIFY(netdef->bond_params.primary_reselect_policy); + FREE_AND_NULLIFY(netdef->bond_params.learn_interval); + FREE_AND_NULLIFY(netdef->bond_params.primary_slave); + memset(&netdef->bond_params, 0, sizeof(netdef->bond_params)); + + FREE_AND_NULLIFY(netdef->modem_params.apn); + FREE_AND_NULLIFY(netdef->modem_params.device_id); + FREE_AND_NULLIFY(netdef->modem_params.network_id); + FREE_AND_NULLIFY(netdef->modem_params.number); + FREE_AND_NULLIFY(netdef->modem_params.password); + FREE_AND_NULLIFY(netdef->modem_params.pin); + FREE_AND_NULLIFY(netdef->modem_params.sim_id); + FREE_AND_NULLIFY(netdef->modem_params.sim_operator_id); + FREE_AND_NULLIFY(netdef->modem_params.username); + memset(&netdef->modem_params, 0, sizeof(netdef->modem_params)); + + FREE_AND_NULLIFY(netdef->bridge_params.ageing_time); + FREE_AND_NULLIFY(netdef->bridge_params.forward_delay); + FREE_AND_NULLIFY(netdef->bridge_params.hello_time); + FREE_AND_NULLIFY(netdef->bridge_params.max_age); + memset(&netdef->bridge_params, 0, sizeof(netdef->bridge_params)); + netdef->custom_bridging = FALSE; + + FREE_AND_NULLIFY(netdef->tunnel.local_ip); + FREE_AND_NULLIFY(netdef->tunnel.remote_ip); + FREE_AND_NULLIFY(netdef->tunnel.input_key); + FREE_AND_NULLIFY(netdef->tunnel.output_key); + FREE_AND_NULLIFY(netdef->tunnel.private_key); + memset(&netdef->tunnel, 0, sizeof(netdef->tunnel)); + netdef->tunnel.mode = NETPLAN_TUNNEL_MODE_UNKNOWN; + + reset_auth_settings(&netdef->auth); + netdef->has_auth = FALSE; + + netdef->sriov_link = NULL; + netdef->sriov_vlan_filter = FALSE; + netdef->sriov_explicit_vf_count = G_MAXUINT; /* 0 is a valid number of VFs */ + + reset_ovs_settings(&netdef->ovs_settings); + reset_backend_settings(&netdef->backend_settings, backend); + + FREE_AND_NULLIFY(netdef->filename); + netdef->tunnel_ttl = 0; + FREE_AND_NULLIFY(netdef->activation_mode); + netdef->ignore_carrier = FALSE; +} diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..48c7ad2 --- /dev/null +++ b/src/types.h @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2021 Canonical, Ltd. + * Author: Simon Chopin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "parse.h" +#include +#include +#include + +typedef enum { + NETPLAN_RA_MODE_KERNEL, + NETPLAN_RA_MODE_ENABLED, + NETPLAN_RA_MODE_DISABLED, +} NetplanRAMode; + +typedef enum { + NETPLAN_OPTIONAL_IPV4_LL = 1<<0, + NETPLAN_OPTIONAL_IPV6_RA = 1<<1, + NETPLAN_OPTIONAL_DHCP4 = 1<<2, + NETPLAN_OPTIONAL_DHCP6 = 1<<3, + NETPLAN_OPTIONAL_STATIC = 1<<4, +} NetplanOptionalAddressFlag; + +typedef enum { + NETPLAN_ADDRGEN_DEFAULT, + NETPLAN_ADDRGEN_EUI64, + NETPLAN_ADDRGEN_STABLEPRIVACY, + NETPLAN_ADDRGEN_MAX, +} NetplanAddrGenMode; + +struct NetplanOptionalAddressType { + char* name; + NetplanOptionalAddressFlag flag; +}; + +// Not strictly speaking a type, but seems fair to keep it around. +extern struct NetplanOptionalAddressType NETPLAN_OPTIONAL_ADDRESS_TYPES[]; + +/* Tunnel mode enum; sync with NetworkManager's DBUS API */ +/* TODO: figure out whether networkd's GRETAP and NM's ISATAP + * are the same thing. + */ +typedef enum { + NETPLAN_TUNNEL_MODE_UNKNOWN = 0, + NETPLAN_TUNNEL_MODE_IPIP = 1, + NETPLAN_TUNNEL_MODE_GRE = 2, + NETPLAN_TUNNEL_MODE_SIT = 3, + NETPLAN_TUNNEL_MODE_ISATAP = 4, // NM only. + NETPLAN_TUNNEL_MODE_VTI = 5, + NETPLAN_TUNNEL_MODE_IP6IP6 = 6, + NETPLAN_TUNNEL_MODE_IPIP6 = 7, + NETPLAN_TUNNEL_MODE_IP6GRE = 8, + NETPLAN_TUNNEL_MODE_VTI6 = 9, + + /* systemd-only, apparently? */ + NETPLAN_TUNNEL_MODE_GRETAP = 101, + NETPLAN_TUNNEL_MODE_IP6GRETAP = 102, + NETPLAN_TUNNEL_MODE_WIREGUARD = 103, + + NETPLAN_TUNNEL_MODE_MAX_, +} NetplanTunnelMode; + +typedef enum { + NETPLAN_WIFI_WOWLAN_DEFAULT = 1<<0, + NETPLAN_WIFI_WOWLAN_ANY = 1<<1, + NETPLAN_WIFI_WOWLAN_DISCONNECT = 1<<2, + NETPLAN_WIFI_WOWLAN_MAGIC = 1<<3, + NETPLAN_WIFI_WOWLAN_GTK_REKEY_FAILURE = 1<<4, + NETPLAN_WIFI_WOWLAN_EAP_IDENTITY_REQ = 1<<5, + NETPLAN_WIFI_WOWLAN_4WAY_HANDSHAKE = 1<<6, + NETPLAN_WIFI_WOWLAN_RFKILL_RELEASE = 1<<7, + NETPLAN_WIFI_WOWLAN_TCP = 1<<8, +} NetplanWifiWowlanFlag; + +struct NetplanWifiWowlanType { + char* name; + NetplanWifiWowlanFlag flag; +}; + +extern struct NetplanWifiWowlanType NETPLAN_WIFI_WOWLAN_TYPES[]; + +typedef enum { + NETPLAN_AUTH_KEY_MANAGEMENT_NONE, + NETPLAN_AUTH_KEY_MANAGEMENT_WPA_PSK, + NETPLAN_AUTH_KEY_MANAGEMENT_WPA_EAP, + NETPLAN_AUTH_KEY_MANAGEMENT_8021X, + NETPLAN_AUTH_KEY_MANAGEMENT_MAX, +} NetplanAuthKeyManagementType; + +typedef enum { + NETPLAN_AUTH_EAP_NONE, + NETPLAN_AUTH_EAP_TLS, + NETPLAN_AUTH_EAP_PEAP, + NETPLAN_AUTH_EAP_TTLS, + NETPLAN_AUTH_EAP_METHOD_MAX, +} NetplanAuthEAPMethod; + +typedef struct missing_node { + char* netdef_id; + const yaml_node_t* node; +} NetplanMissingNode; + +typedef struct authentication_settings { + NetplanAuthKeyManagementType key_management; + NetplanAuthEAPMethod eap_method; + char* identity; + char* anonymous_identity; + char* password; + char* ca_certificate; + char* client_certificate; + char* client_key; + char* client_key_password; + char* phase2_auth; /* netplan-feature: auth-phase2 */ +} NetplanAuthenticationSettings; + +/* Fields below are valid for dhcp4 and dhcp6 unless otherwise noted. */ +typedef struct dhcp_overrides { + gboolean use_dns; + gboolean use_ntp; + gboolean send_hostname; + gboolean use_hostname; + gboolean use_mtu; + gboolean use_routes; + char* use_domains; /* netplan-feature: dhcp-use-domains */ + char* hostname; + guint metric; +} NetplanDHCPOverrides; + +typedef struct ovs_controller { + char* connection_mode; + GArray* addresses; +} NetplanOVSController; + +typedef struct ovs_settings { + GHashTable* external_ids; + GHashTable* other_config; + char* lacp; + char* fail_mode; + gboolean mcast_snooping; + GArray* protocols; + gboolean rstp; + NetplanOVSController controller; + NetplanAuthenticationSettings ssl; +} NetplanOVSSettings; + +typedef union { + struct NetplanNMSettings { + char *name; + char *uuid; + char *stable_id; + char *device; + GData* passthrough; /* See g_datalist* functions */ + } nm; + struct NetplanNetworkdSettings { + char *unit; + } networkd; +} NetplanBackendSettings; + +struct net_definition { + NetplanDefType type; + NetplanBackend backend; + char* id; + /* only necessary for NetworkManager connection UUIDs in some cases */ + uuid_t uuid; + + /* status options */ + gboolean optional; + NetplanOptionalAddressFlag optional_addresses; + gboolean critical; + + /* addresses */ + gboolean dhcp4; + gboolean dhcp6; + char* dhcp_identifier; + NetplanDHCPOverrides dhcp4_overrides; + NetplanDHCPOverrides dhcp6_overrides; + NetplanRAMode accept_ra; + GArray* ip4_addresses; + GArray* ip6_addresses; + GArray* address_options; + gboolean ip6_privacy; + guint ip6_addr_gen_mode; + char* ip6_addr_gen_token; + char* gateway4; + char* gateway6; + GArray* ip4_nameservers; + GArray* ip6_nameservers; + GArray* search_domains; + GArray* routes; + GArray* ip_rules; + GArray* wireguard_peers; + struct { + gboolean ipv4; + gboolean ipv6; + } linklocal; + + /* master ID for slave devices */ + char* bridge; + char* bond; + + /* peer ID for OVS patch ports */ + char* peer; + + /* vlan */ + guint vlan_id; + NetplanNetDefinition* vlan_link; + gboolean has_vlans; + + /* Configured custom MAC address */ + char* set_mac; + + /* interface mtu */ + guint mtubytes; + /* ipv6 mtu */ + /* netplan-feature: ipv6-mtu */ + guint ipv6_mtubytes; + + /* these properties are only valid for physical interfaces (type < ND_VIRTUAL) */ + char* set_name; + struct { + char* driver; + char* mac; + char* original_name; + } match; + gboolean has_match; + gboolean wake_on_lan; + NetplanWifiWowlanFlag wowlan; + gboolean emit_lldp; + + /* these properties are only valid for NETPLAN_DEF_TYPE_WIFI */ + GHashTable* access_points; /* SSID → NetplanWifiAccessPoint* */ + + struct { + char* mode; + char* lacp_rate; + char* monitor_interval; + guint min_links; + char* transmit_hash_policy; + char* selection_logic; + gboolean all_slaves_active; + char* arp_interval; + GArray* arp_ip_targets; + char* arp_validate; + char* arp_all_targets; + char* up_delay; + char* down_delay; + char* fail_over_mac_policy; + guint gratuitous_arp; + /* TODO: unsolicited_na */ + guint packets_per_slave; + char* primary_reselect_policy; + guint resend_igmp; + char* learn_interval; + char* primary_slave; + } bond_params; + + /* netplan-feature: modems */ + struct { + char* apn; + gboolean auto_config; + char* device_id; + char* network_id; + char* number; + char* password; + char* pin; + char* sim_id; + char* sim_operator_id; + char* username; + } modem_params; + + struct { + char* ageing_time; + guint priority; + guint port_priority; + char* forward_delay; + char* hello_time; + char* max_age; + guint path_cost; + gboolean stp; + } bridge_params; + gboolean custom_bridging; + + struct { + NetplanTunnelMode mode; + char *local_ip; + char *remote_ip; + char *input_key; + char *output_key; + char *private_key; /* used for wireguard */ + guint fwmark; + guint port; + } tunnel; + + NetplanAuthenticationSettings auth; + gboolean has_auth; + + /* these properties are only valid for SR-IOV NICs */ + /* netplan-feature: sriov */ + struct net_definition* sriov_link; + gboolean sriov_vlan_filter; + guint sriov_explicit_vf_count; + + /* these properties are only valid for OpenVSwitch */ + /* netplan-feature: openvswitch */ + NetplanOVSSettings ovs_settings; + + NetplanBackendSettings backend_settings; + + char* filename; + /* it cannot be in the tunnel struct: https://github.com/canonical/netplan/pull/206 */ + guint tunnel_ttl; + + /* netplan-feature: activation-mode */ + char* activation_mode; + + /* configure without carrier */ + gboolean ignore_carrier; + + /* offload options */ + gboolean receive_checksum_offload; + gboolean transmit_checksum_offload; + gboolean tcp_segmentation_offload; + gboolean tcp6_segmentation_offload; + gboolean generic_segmentation_offload; + gboolean generic_receive_offload; + gboolean large_receive_offload; +}; + +typedef enum { + NETPLAN_WIFI_MODE_INFRASTRUCTURE, + NETPLAN_WIFI_MODE_ADHOC, + NETPLAN_WIFI_MODE_AP, + NETPLAN_WIFI_MODE_OTHER, + NETPLAN_WIFI_MODE_MAX_ +} NetplanWifiMode; + +typedef struct { + char *endpoint; + char *public_key; + char *preshared_key; + GArray *allowed_ips; + guint keepalive; +} NetplanWireguardPeer; + +typedef enum { + NETPLAN_WIFI_BAND_DEFAULT, + NETPLAN_WIFI_BAND_5, + NETPLAN_WIFI_BAND_24 +} NetplanWifiBand; + +typedef struct { + char* address; + char* lifetime; + char* label; +} NetplanAddressOptions; + +typedef struct { + NetplanWifiMode mode; + char* ssid; + NetplanWifiBand band; + char* bssid; + gboolean hidden; + guint channel; + + NetplanAuthenticationSettings auth; + gboolean has_auth; + + NetplanBackendSettings backend_settings; +} NetplanWifiAccessPoint; + +typedef struct { + guint family; + char* type; + char* scope; + guint table; + + char* from; + char* to; + char* via; + + gboolean onlink; + + /* valid metrics are valid positive integers. + * invalid metrics are represented by METRIC_UNSPEC */ + guint metric; + + guint mtubytes; + guint congestion_window; + guint advertised_receive_window; +} NetplanIPRoute; + +typedef struct { + guint family; + + char* from; + char* to; + + /* table: Valid values are 1 <= x <= 4294967295) */ + guint table; + guint priority; + /* fwmark: Valid values are 1 <= x <= 4294967295) */ + guint fwmark; + /* type-of-service: between 0 and 255 */ + guint tos; +} NetplanIPRule; + +#define NETPLAN_ADVERTISED_RECEIVE_WINDOW_UNSPEC 0 +#define NETPLAN_CONGESTION_WINDOW_UNSPEC 0 +#define NETPLAN_MTU_UNSPEC 0 +#define NETPLAN_METRIC_UNSPEC G_MAXUINT +#define NETPLAN_ROUTE_TABLE_UNSPEC 0 +#define NETPLAN_IP_RULE_PRIO_UNSPEC G_MAXUINT +#define NETPLAN_IP_RULE_FW_MARK_UNSPEC 0 +#define NETPLAN_IP_RULE_TOS_UNSPEC G_MAXUINT + +void reset_netdef(NetplanNetDefinition *netdef, NetplanDefType type, NetplanBackend renderer); diff --git a/src/util-internal.h b/src/util-internal.h new file mode 100644 index 0000000..fe792d4 --- /dev/null +++ b/src/util-internal.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 Canonical, Ltd. + * Author: Martin Pitt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#define __USE_MISC +#include +#include +#include "types.h" + +#include +#include "netplan.h" + +extern GHashTable* +wifi_frequency_24; + +extern GHashTable* +wifi_frequency_5; + +NETPLAN_ABI void +safe_mkdir_p_dir(const char* file_path); + +NETPLAN_INTERNAL void +g_string_free_to_file(GString* s, const char* rootdir, const char* path, const char* suffix); + +NETPLAN_INTERNAL void +unlink_glob(const char* rootdir, const char* _glob); + +NETPLAN_INTERNAL int +find_yaml_glob(const char* rootdir, glob_t* out_glob); + +NETPLAN_ABI const char* +get_global_network(int ip_family); + +NETPLAN_ABI int +wifi_get_freq24(int channel); + +NETPLAN_ABI int +wifi_get_freq5(int channel); + +NETPLAN_ABI gchar* +systemd_escape(char* string); + +#define OPENVSWITCH_OVS_VSCTL "/usr/bin/ovs-vsctl" + +const char* +tunnel_mode_to_string(NetplanTunnelMode mode); + +NetplanNetDefinition* +netplan_netdef_new(const char* id, NetplanDefType type, NetplanBackend renderer); + +NETPLAN_INTERNAL void +process_input_file(const char* f); + +NETPLAN_INTERNAL gboolean +process_yaml_hierarchy(const char* rootdir); diff --git a/src/util.c b/src/util.c index b43aaf9..c8004cf 100644 --- a/src/util.c +++ b/src/util.c @@ -23,11 +23,17 @@ #include #include "util.h" +#include "util-internal.h" #include "netplan.h" +#include "parse.h" +#include "parse-globals.h" #include "names.h" -GHashTable* wifi_frequency_24; -GHashTable* wifi_frequency_5; +NETPLAN_ABI GHashTable* +wifi_frequency_24; + +NETPLAN_ABI GHashTable* +wifi_frequency_5; /** * Create the parent directories of given file path. Exit program on failure. diff --git a/src/util.h b/src/util.h deleted file mode 100644 index f34c601..0000000 --- a/src/util.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016 Canonical, Ltd. - * Author: Martin Pitt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#define __USE_MISC -#include -#pragma once - -extern GHashTable* wifi_frequency_24; -extern GHashTable* wifi_frequency_5; - -void safe_mkdir_p_dir(const char* file_path); -void g_string_free_to_file(GString* s, const char* rootdir, const char* path, const char* suffix); -void unlink_glob(const char* rootdir, const char* _glob); -int find_yaml_glob(const char* rootdir, glob_t* out_glob); - -const char *get_global_network(int ip_family); - -int wifi_get_freq24(int channel); -int wifi_get_freq5(int channel); - -gchar* systemd_escape(char* string); -gboolean netplan_delete_connection(const char* id, const char* rootdir); -gboolean netplan_generate(const char* rootdir); -gchar* netplan_get_id_from_nm_filename(const char* filename, const char* ssid); -gchar* netplan_get_filename_by_id(const char* netdef_id, const char* rootdir); - -#define OPENVSWITCH_OVS_VSCTL "/usr/bin/ovs-vsctl" diff --git a/src/validation.c b/src/validation.c index 2ac5650..7b80559 100644 --- a/src/validation.c +++ b/src/validation.c @@ -24,10 +24,12 @@ #include #include "parse.h" +#include "types.h" +#include "parse-globals.h" #include "names.h" #include "error.h" -#include "util.h" - +#include "util-internal.h" +#include "validation.h" /* Check sanity for address types */ diff --git a/src/validation.h b/src/validation.h index 3f6e527..18e98fe 100644 --- a/src/validation.h +++ b/src/validation.h @@ -19,14 +19,17 @@ #include "parse.h" #include +#include gboolean is_ip4_address(const char* address); gboolean is_ip6_address(const char* address); gboolean is_hostname(const char* hostname); -gboolean is_wireguard_key(const char* hostname); gboolean validate_ovs_target(gboolean host_first, gchar* s); +NETPLAN_ABI gboolean +is_wireguard_key(const char* hostname); + gboolean validate_netdef_grammar(NetplanNetDefinition* nd, yaml_node_t* node, GError** error); diff --git a/src/yaml-helpers.h b/src/yaml-helpers.h new file mode 100644 index 0000000..6408ac1 --- /dev/null +++ b/src/yaml-helpers.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 Canonical, Ltd. + * Author: Martin Pitt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#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; \ +} +#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; \ +} +#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; \ +} +#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; \ +} +#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; \ +} +/* 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; \ +} +#define YAML_STRING(event_ptr, emitter_ptr, key, value_ptr) \ +{ \ + if (value_ptr) { \ + YAML_SCALAR_PLAIN(event_ptr, emitter_ptr, key); \ + YAML_SCALAR_QUOTED(event_ptr, emitter_ptr, value_ptr); \ + } \ +} +#define YAML_STRING_PLAIN(event_ptr, emitter_ptr, key, value_ptr) \ +{ \ + if (value_ptr) { \ + YAML_SCALAR_PLAIN(event_ptr, emitter_ptr, key); \ + YAML_SCALAR_PLAIN(event_ptr, emitter_ptr, value_ptr); \ + } \ +} +#define YAML_UINT(event_ptr, emitter_ptr, key, value) \ +{ \ + tmp = g_strdup_printf("%u", value); \ + YAML_STRING_PLAIN(event_ptr, emitter_ptr, key, tmp); \ + g_free(tmp); \ +} + +/* open YAML emitter, document, stream and initial mapping */ +#define YAML_OUT_START(event_ptr, emitter_ptr, file) \ +{ \ + 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; \ + yaml_document_start_event_initialize(event_ptr, NULL, NULL, NULL, 1); \ + if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \ + YAML_MAPPING_OPEN(event_ptr, emitter_ptr); \ +} +/* close initial YAML mapping, document, stream and emitter */ +#define YAML_OUT_STOP(event_ptr, emitter_ptr) \ +{ \ + 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; \ + yaml_stream_end_event_initialize(event_ptr); \ + if (!yaml_emitter_emit(emitter_ptr, event_ptr)) goto error; \ + yaml_emitter_delete(emitter_ptr); \ +} -- cgit v1.2.3