diff options
Diffstat (limited to 'src/types.c')
-rw-r--r-- | src/types.c | 317 |
1 files changed, 317 insertions, 0 deletions
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 <simon.chopin@canonical.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +/* This module contains functions to deal with the Netplan objects, + * notably, accessors and destructors. Note that types specific to parsing + * are implemented separately. + */ + +#include <glib.h> +#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; +} |