mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-03-06 00:00:31 +01:00
cloud-setup: merge branch 'backport_1_30_mr_974'
NetworkManager/NetworkManager!987
This commit is contained in:
commit
9366a4404f
12 changed files with 457 additions and 184 deletions
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "nm-libnm-aux/nm-libnm-aux.h"
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "nm-cloud-setup-utils.h"
|
||||
#include "nmcs-provider-ec2.h"
|
||||
#include "nmcs-provider-gcp.h"
|
||||
|
|
@ -198,30 +200,30 @@ _nmc_get_device_by_hwaddr(NMClient *nmc, const char *hwaddr)
|
|||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GMainLoop * main_loop;
|
||||
GHashTable *config_dict;
|
||||
GMainLoop * main_loop;
|
||||
NMCSProviderGetConfigResult *result;
|
||||
} GetConfigData;
|
||||
|
||||
static void
|
||||
_get_config_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
_get_config_cb(GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
GetConfigData * data = user_data;
|
||||
gs_unref_hashtable GHashTable *config_dict = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
GetConfigData * data = user_data;
|
||||
nm_auto_free_nmcs_provider_get_config_result NMCSProviderGetConfigResult *result = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
config_dict = nmcs_provider_get_config_finish(NMCS_PROVIDER(source), result, &error);
|
||||
result = nmcs_provider_get_config_finish(NMCS_PROVIDER(source), res, &error);
|
||||
|
||||
if (!config_dict) {
|
||||
if (!result) {
|
||||
if (!nm_utils_error_is_cancelled(error))
|
||||
_LOGI("failure to get meta data: %s", error->message);
|
||||
} else
|
||||
_LOGD("meta data received");
|
||||
|
||||
data->config_dict = g_steal_pointer(&config_dict);
|
||||
data->result = g_steal_pointer(&result);
|
||||
g_main_loop_quit(data->main_loop);
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
static NMCSProviderGetConfigResult *
|
||||
_get_config(GCancellable *sigterm_cancellable, NMCSProvider *provider, NMClient *nmc)
|
||||
{
|
||||
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
|
||||
|
|
@ -241,7 +243,7 @@ _get_config(GCancellable *sigterm_cancellable, NMCSProvider *provider, NMClient
|
|||
|
||||
g_main_loop_run(main_loop);
|
||||
|
||||
return data.config_dict;
|
||||
return data.result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -267,22 +269,26 @@ _nmc_skip_connection(NMConnection *connection)
|
|||
static gboolean
|
||||
_nmc_mangle_connection(NMDevice * device,
|
||||
NMConnection * connection,
|
||||
const NMCSProviderGetConfigResult * result,
|
||||
const NMCSProviderGetConfigIfaceData *config_data,
|
||||
gboolean * out_skipped_single_addr,
|
||||
gboolean * out_changed)
|
||||
{
|
||||
NMSettingIPConfig *s_ip;
|
||||
gsize i;
|
||||
in_addr_t gateway;
|
||||
gint64 rt_metric;
|
||||
guint32 rt_table;
|
||||
NMIPRoute * route_entry;
|
||||
gboolean addrs_changed = FALSE;
|
||||
gboolean rules_changed = FALSE;
|
||||
gboolean routes_changed = FALSE;
|
||||
NMSettingIPConfig * s_ip;
|
||||
NMActiveConnection *ac;
|
||||
NMConnection * remote_connection;
|
||||
NMSettingIPConfig * remote_s_ip = NULL;
|
||||
gsize i;
|
||||
gboolean addrs_changed = FALSE;
|
||||
gboolean rules_changed = FALSE;
|
||||
gboolean routes_changed = FALSE;
|
||||
gs_unref_ptrarray GPtrArray *addrs_new = NULL;
|
||||
gs_unref_ptrarray GPtrArray *rules_new = NULL;
|
||||
gs_unref_ptrarray GPtrArray *routes_new = NULL;
|
||||
|
||||
NM_SET_OUT(out_skipped_single_addr, FALSE);
|
||||
NM_SET_OUT(out_changed, FALSE);
|
||||
|
||||
if (!nm_streq0(nm_connection_get_connection_type(connection), NM_SETTING_WIRED_SETTING_NAME))
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -290,52 +296,118 @@ _nmc_mangle_connection(NMDevice * device,
|
|||
if (!s_ip)
|
||||
return FALSE;
|
||||
|
||||
if ((ac = nm_device_get_active_connection(device))
|
||||
&& (remote_connection = NM_CONNECTION(nm_active_connection_get_connection(ac))))
|
||||
remote_s_ip = nm_connection_get_setting_ip4_config(remote_connection);
|
||||
|
||||
addrs_new = g_ptr_array_new_full(config_data->ipv4s_len, (GDestroyNotify) nm_ip_address_unref);
|
||||
rules_new =
|
||||
g_ptr_array_new_full(config_data->ipv4s_len, (GDestroyNotify) nm_ip_routing_rule_unref);
|
||||
routes_new = g_ptr_array_new_full(config_data->iproutes_len + !!config_data->ipv4s_len,
|
||||
(GDestroyNotify) nm_ip_route_unref);
|
||||
|
||||
if (config_data->has_ipv4s && config_data->has_cidr) {
|
||||
for (i = 0; i < config_data->ipv4s_len; i++) {
|
||||
NMIPAddress *entry;
|
||||
if (remote_s_ip) {
|
||||
guint len;
|
||||
guint j;
|
||||
|
||||
entry = nm_ip_address_new_binary(AF_INET,
|
||||
&config_data->ipv4s_arr[i],
|
||||
config_data->cidr_prefix,
|
||||
NULL);
|
||||
if (entry)
|
||||
g_ptr_array_add(addrs_new, entry);
|
||||
len = nm_setting_ip_config_get_num_addresses(remote_s_ip);
|
||||
for (j = 0; j < len; j++) {
|
||||
g_ptr_array_add(addrs_new,
|
||||
nm_ip_address_dup(nm_setting_ip_config_get_address(remote_s_ip, j)));
|
||||
}
|
||||
|
||||
gateway = nm_utils_ip4_address_clear_host_address(config_data->cidr_addr,
|
||||
config_data->cidr_prefix);
|
||||
((guint8 *) &gateway)[3] += 1;
|
||||
len = nm_setting_ip_config_get_num_routes(remote_s_ip);
|
||||
for (j = 0; j < len; j++) {
|
||||
g_ptr_array_add(routes_new,
|
||||
nm_ip_route_dup(nm_setting_ip_config_get_route(remote_s_ip, j)));
|
||||
}
|
||||
|
||||
rt_metric = 10;
|
||||
rt_table = 30400 + config_data->iface_idx;
|
||||
len = nm_setting_ip_config_get_num_routing_rules(remote_s_ip);
|
||||
for (j = 0; j < len; j++) {
|
||||
g_ptr_array_add(
|
||||
rules_new,
|
||||
nm_ip_routing_rule_ref(nm_setting_ip_config_get_routing_rule(remote_s_ip, j)));
|
||||
}
|
||||
}
|
||||
|
||||
route_entry =
|
||||
nm_ip_route_new_binary(AF_INET, &nm_ip_addr_zero, 0, &gateway, rt_metric, NULL);
|
||||
if (result->num_valid_ifaces <= 1 && result->num_ipv4s <= 1) {
|
||||
/* this setup only has one interface and one IPv4 address (or less).
|
||||
* We don't need to configure policy routing in this case. */
|
||||
NM_SET_OUT(out_skipped_single_addr, TRUE);
|
||||
} else if (config_data->has_ipv4s && config_data->has_cidr) {
|
||||
gs_unref_hashtable GHashTable *unique_subnets =
|
||||
g_hash_table_new(nm_direct_hash, g_direct_equal);
|
||||
NMIPAddress * addr_entry;
|
||||
NMIPRoute * route_entry;
|
||||
NMIPRoutingRule *rule_entry;
|
||||
in_addr_t gateway;
|
||||
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
|
||||
for (i = 0; i < config_data->ipv4s_len; i++) {
|
||||
addr_entry = nm_ip_address_new_binary(AF_INET,
|
||||
&config_data->ipv4s_arr[i],
|
||||
config_data->cidr_prefix,
|
||||
NULL);
|
||||
nm_assert(addr_entry);
|
||||
g_ptr_array_add(addrs_new, addr_entry);
|
||||
}
|
||||
|
||||
if (config_data->has_gateway && config_data->gateway) {
|
||||
gateway = config_data->gateway;
|
||||
} else {
|
||||
gateway = nm_utils_ip4_address_clear_host_address(config_data->cidr_addr,
|
||||
config_data->cidr_prefix);
|
||||
if (config_data->cidr_prefix < 32)
|
||||
((guint8 *) &gateway)[3] += 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < config_data->ipv4s_len; i++) {
|
||||
in_addr_t a = config_data->ipv4s_arr[i];
|
||||
|
||||
a = nm_utils_ip4_address_clear_host_address(a, config_data->cidr_prefix);
|
||||
|
||||
G_STATIC_ASSERT_EXPR(sizeof(gsize) >= sizeof(in_addr_t));
|
||||
if (g_hash_table_add(unique_subnets, GSIZE_TO_POINTER(a))) {
|
||||
route_entry =
|
||||
nm_ip_route_new_binary(AF_INET, &a, config_data->cidr_prefix, NULL, 10, NULL);
|
||||
nm_ip_route_set_attribute(route_entry,
|
||||
NM_IP_ROUTE_ATTRIBUTE_TABLE,
|
||||
g_variant_new_uint32(30200 + config_data->iface_idx));
|
||||
g_ptr_array_add(routes_new, route_entry);
|
||||
}
|
||||
|
||||
rule_entry = nm_ip_routing_rule_new(AF_INET);
|
||||
nm_ip_routing_rule_set_priority(rule_entry, 30200 + config_data->iface_idx);
|
||||
nm_ip_routing_rule_set_from(rule_entry,
|
||||
_nm_utils_inet4_ntop(config_data->ipv4s_arr[i], sbuf),
|
||||
32);
|
||||
nm_ip_routing_rule_set_table(rule_entry, 30200 + config_data->iface_idx);
|
||||
nm_assert(nm_ip_routing_rule_validate(rule_entry, NULL));
|
||||
g_ptr_array_add(rules_new, rule_entry);
|
||||
}
|
||||
|
||||
rule_entry = nm_ip_routing_rule_new(AF_INET);
|
||||
nm_ip_routing_rule_set_priority(rule_entry, 30350);
|
||||
nm_ip_routing_rule_set_table(rule_entry, RT_TABLE_MAIN);
|
||||
nm_ip_routing_rule_set_suppress_prefixlength(rule_entry, 0);
|
||||
nm_assert(nm_ip_routing_rule_validate(rule_entry, NULL));
|
||||
g_ptr_array_add(rules_new, rule_entry);
|
||||
|
||||
route_entry = nm_ip_route_new_binary(AF_INET, &nm_ip_addr_zero, 0, &gateway, 10, NULL);
|
||||
nm_ip_route_set_attribute(route_entry,
|
||||
NM_IP_ROUTE_ATTRIBUTE_TABLE,
|
||||
g_variant_new_uint32(rt_table));
|
||||
g_variant_new_uint32(30400 + config_data->iface_idx));
|
||||
g_ptr_array_add(routes_new, route_entry);
|
||||
|
||||
for (i = 0; i < config_data->ipv4s_len; i++) {
|
||||
NMIPRoutingRule *entry;
|
||||
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
|
||||
entry = nm_ip_routing_rule_new(AF_INET);
|
||||
nm_ip_routing_rule_set_priority(entry, rt_table);
|
||||
nm_ip_routing_rule_set_from(entry,
|
||||
rule_entry = nm_ip_routing_rule_new(AF_INET);
|
||||
nm_ip_routing_rule_set_priority(rule_entry, 30400 + config_data->iface_idx);
|
||||
nm_ip_routing_rule_set_from(rule_entry,
|
||||
_nm_utils_inet4_ntop(config_data->ipv4s_arr[i], sbuf),
|
||||
32);
|
||||
nm_ip_routing_rule_set_table(entry, rt_table);
|
||||
|
||||
nm_assert(nm_ip_routing_rule_validate(entry, NULL));
|
||||
|
||||
g_ptr_array_add(rules_new, entry);
|
||||
nm_ip_routing_rule_set_table(rule_entry, 30400 + config_data->iface_idx);
|
||||
nm_assert(nm_ip_routing_rule_validate(rule_entry, NULL));
|
||||
g_ptr_array_add(rules_new, rule_entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -360,34 +432,20 @@ _nmc_mangle_connection(NMDevice * device,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint
|
||||
_config_data_get_num_valid(GHashTable *config_dict)
|
||||
{
|
||||
const NMCSProviderGetConfigIfaceData *config_data;
|
||||
GHashTableIter h_iter;
|
||||
guint n = 0;
|
||||
|
||||
g_hash_table_iter_init(&h_iter, config_dict);
|
||||
while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &config_data)) {
|
||||
if (nmcs_provider_get_config_iface_data_is_valid(config_data))
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_config_one(GCancellable * sigterm_cancellable,
|
||||
NMClient * nmc,
|
||||
gboolean is_single_nic,
|
||||
const char * hwaddr,
|
||||
const NMCSProviderGetConfigIfaceData *config_data)
|
||||
_config_one(GCancellable * sigterm_cancellable,
|
||||
NMClient * nmc,
|
||||
const NMCSProviderGetConfigResult *result,
|
||||
guint idx)
|
||||
{
|
||||
gs_unref_object NMDevice *device = NULL;
|
||||
gs_unref_object NMConnection *applied_connection = NULL;
|
||||
const NMCSProviderGetConfigIfaceData *config_data = result->iface_datas_arr[idx];
|
||||
const char * hwaddr = config_data->hwaddr;
|
||||
gs_unref_object NMDevice *device = NULL;
|
||||
gs_unref_object NMConnection *applied_connection = NULL;
|
||||
guint64 applied_version_id;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean changed;
|
||||
gboolean skipped_single_addr;
|
||||
gboolean version_id_changed;
|
||||
guint try_count;
|
||||
gboolean any_changes = FALSE;
|
||||
|
|
@ -408,6 +466,14 @@ _config_one(GCancellable * sigterm_cancellable,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (config_data->iface_idx >= 100) {
|
||||
/* since we use the iface_idx to select a table number, the range is limited from
|
||||
* 0 to 99. Note that the providers are required to provide increasing numbers,
|
||||
* so this means we bail out after the first 100 devices. */
|
||||
_LOGD("config device %s: skip because number of supported interfaces reached", hwaddr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_LOGD("config device %s: configuring \"%s\" (%s)...",
|
||||
hwaddr,
|
||||
nm_device_get_iface(device) ?: "/unknown/",
|
||||
|
|
@ -436,16 +502,30 @@ try_again:
|
|||
return any_changes;
|
||||
}
|
||||
|
||||
if (!_nmc_mangle_connection(device, applied_connection, config_data, &changed)) {
|
||||
if (!_nmc_mangle_connection(device,
|
||||
applied_connection,
|
||||
result,
|
||||
config_data,
|
||||
&skipped_single_addr,
|
||||
&changed)) {
|
||||
_LOGD("config device %s: device has no suitable applied connection. Skip", hwaddr);
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
_LOGD("config device %s: device needs no update to applied connection \"%s\" (%s). Skip",
|
||||
hwaddr,
|
||||
nm_connection_get_id(applied_connection),
|
||||
nm_connection_get_uuid(applied_connection));
|
||||
if (skipped_single_addr) {
|
||||
_LOGD("config device %s: device needs no update to applied connection \"%s\" (%s) "
|
||||
"because there are not multiple IP addresses. Skip",
|
||||
hwaddr,
|
||||
nm_connection_get_id(applied_connection),
|
||||
nm_connection_get_uuid(applied_connection));
|
||||
} else {
|
||||
_LOGD(
|
||||
"config device %s: device needs no update to applied connection \"%s\" (%s). Skip",
|
||||
hwaddr,
|
||||
nm_connection_get_id(applied_connection),
|
||||
nm_connection_get_uuid(applied_connection));
|
||||
}
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
|
|
@ -454,7 +534,7 @@ try_again:
|
|||
nm_connection_get_id(applied_connection),
|
||||
nm_connection_get_uuid(applied_connection));
|
||||
|
||||
/* we are about to call Reapply(). If if that fails, it counts as if we changed something. */
|
||||
/* we are about to call Reapply(). Even if that fails, it counts as if we changed something. */
|
||||
any_changes = TRUE;
|
||||
|
||||
if (!nmcs_device_reapply(device,
|
||||
|
|
@ -490,19 +570,15 @@ try_again:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_config_all(GCancellable *sigterm_cancellable, NMClient *nmc, GHashTable *config_dict)
|
||||
_config_all(GCancellable * sigterm_cancellable,
|
||||
NMClient * nmc,
|
||||
const NMCSProviderGetConfigResult *result)
|
||||
{
|
||||
GHashTableIter h_iter;
|
||||
const NMCSProviderGetConfigIfaceData *c_config_data;
|
||||
const char * c_hwaddr;
|
||||
gboolean is_single_nic;
|
||||
gboolean any_changes = FALSE;
|
||||
gboolean any_changes = FALSE;
|
||||
guint i;
|
||||
|
||||
is_single_nic = (_config_data_get_num_valid(config_dict) <= 1);
|
||||
|
||||
g_hash_table_iter_init(&h_iter, config_dict);
|
||||
while (g_hash_table_iter_next(&h_iter, (gpointer *) &c_hwaddr, (gpointer *) &c_config_data)) {
|
||||
if (_config_one(sigterm_cancellable, nmc, is_single_nic, c_hwaddr, c_config_data))
|
||||
for (i = 0; i < result->n_iface_datas; i++) {
|
||||
if (_config_one(sigterm_cancellable, nmc, result, i))
|
||||
any_changes = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -529,12 +605,12 @@ sigterm_handler(gpointer user_data)
|
|||
int
|
||||
main(int argc, const char *const *argv)
|
||||
{
|
||||
gs_unref_object GCancellable * sigterm_cancellable = NULL;
|
||||
nm_auto_destroy_and_unref_gsource GSource *sigterm_source = NULL;
|
||||
gs_unref_object NMCSProvider *provider = NULL;
|
||||
gs_unref_object NMClient *nmc = NULL;
|
||||
gs_unref_hashtable GHashTable *config_dict = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_object GCancellable * sigterm_cancellable = NULL;
|
||||
nm_auto_destroy_and_unref_gsource GSource *sigterm_source = NULL;
|
||||
gs_unref_object NMCSProvider *provider = NULL;
|
||||
gs_unref_object NMClient * nmc = NULL;
|
||||
nm_auto_free_nmcs_provider_get_config_result NMCSProviderGetConfigResult *result = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
_nm_logging_enabled_init(g_getenv(NMCS_ENV_VARIABLE("NM_CLOUD_SETUP_LOG")));
|
||||
|
||||
|
|
@ -579,17 +655,17 @@ main(int argc, const char *const *argv)
|
|||
goto done;
|
||||
}
|
||||
|
||||
config_dict = _get_config(sigterm_cancellable, provider, nmc);
|
||||
if (!config_dict)
|
||||
result = _get_config(sigterm_cancellable, provider, nmc);
|
||||
if (!result)
|
||||
goto done;
|
||||
|
||||
if (_config_all(sigterm_cancellable, nmc, config_dict))
|
||||
if (_config_all(sigterm_cancellable, nmc, result))
|
||||
_LOGI("some changes were applied for provider %s", nmcs_provider_get_name(provider));
|
||||
else
|
||||
_LOGD("no changes were applied for provider %s", nmcs_provider_get_name(provider));
|
||||
|
||||
done:
|
||||
nm_clear_pointer(&config_dict, g_hash_table_unref);
|
||||
nm_clear_pointer(&result, nmcs_provider_get_config_result_free);
|
||||
g_clear_object(&nmc);
|
||||
g_clear_object(&provider);
|
||||
|
||||
|
|
|
|||
|
|
@ -98,8 +98,7 @@ typedef struct {
|
|||
NMCSProviderGetConfigIfaceData *iface_get_config;
|
||||
gssize intern_iface_idx;
|
||||
gssize extern_iface_idx;
|
||||
guint n_ips_prefix_pending;
|
||||
const char * hwaddr;
|
||||
guint n_iface_data_pending;
|
||||
} AzureIfaceData;
|
||||
|
||||
static void
|
||||
|
|
@ -118,8 +117,9 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
|
|||
NMCSProviderGetConfigIfaceData *iface_get_config;
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char * fip_str = NULL;
|
||||
gsize fip_len;
|
||||
gs_free char * v_hwaddr = NULL;
|
||||
const char * resp_str = NULL;
|
||||
gsize resp_len;
|
||||
|
||||
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
|
||||
|
||||
|
|
@ -131,18 +131,27 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
|
|||
if (error)
|
||||
goto out_done;
|
||||
|
||||
fip_str = g_bytes_get_data(response, &fip_len);
|
||||
nm_assert(fip_str[fip_len] == '\0');
|
||||
resp_str = g_bytes_get_data(response, &resp_len);
|
||||
nm_assert(resp_str[resp_len] == '\0');
|
||||
|
||||
iface_data->iface_get_config =
|
||||
g_hash_table_lookup(get_config_data->result_dict, iface_data->hwaddr);
|
||||
iface_get_config = iface_data->iface_get_config;
|
||||
v_hwaddr = nmcs_utils_hwaddr_normalize_gbytes(response);
|
||||
if (!v_hwaddr) {
|
||||
_LOGI("interface[%" G_GSSIZE_FORMAT "]: invalid MAC address returned",
|
||||
iface_data->intern_iface_idx);
|
||||
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
|
||||
"invalid MAC address for index %" G_GSSIZE_FORMAT,
|
||||
iface_data->intern_iface_idx);
|
||||
goto out_done;
|
||||
}
|
||||
|
||||
iface_data->iface_get_config = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
||||
iface_get_config = iface_data->iface_get_config;
|
||||
|
||||
if (is_ipv4) {
|
||||
char tmp_addr_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
in_addr_t tmp_addr;
|
||||
|
||||
if (!nmcs_utils_ipaddr_normalize_bin(AF_INET, fip_str, fip_len, NULL, &tmp_addr)) {
|
||||
if (!nmcs_utils_ipaddr_normalize_bin(AF_INET, resp_str, resp_len, NULL, &tmp_addr)) {
|
||||
error =
|
||||
nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "ip is not a valid private ip address");
|
||||
goto out_done;
|
||||
|
|
@ -154,14 +163,9 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
|
|||
iface_get_config->has_ipv4s = TRUE;
|
||||
iface_get_config->ipv4s_len++;
|
||||
} else {
|
||||
int tmp_prefix = -1;
|
||||
|
||||
if (fip_len > 0 && memchr(fip_str, '\0', fip_len - 1)) {
|
||||
/* we have an embedded "\0" inside the string (except trailing). That is not
|
||||
* allowed*/
|
||||
} else
|
||||
tmp_prefix = _nm_utils_ascii_str_to_int64(fip_str, 10, 0, 32, -1);
|
||||
int tmp_prefix;
|
||||
|
||||
tmp_prefix = _nm_utils_ascii_str_to_int64_bin(resp_str, resp_len, 10, 0, 32, -1);
|
||||
if (tmp_prefix == -1) {
|
||||
_LOGD("interface[%" G_GSSIZE_FORMAT "]: invalid prefix", iface_data->intern_iface_idx);
|
||||
error =
|
||||
|
|
@ -178,8 +182,8 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
|
|||
|
||||
out_done:
|
||||
if (!error) {
|
||||
--iface_data->n_ips_prefix_pending;
|
||||
if (iface_data->n_ips_prefix_pending > 0)
|
||||
--iface_data->n_iface_data_pending;
|
||||
if (iface_data->n_iface_data_pending > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +248,6 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
|
|||
((char *) line)[--line_len] = '\0';
|
||||
|
||||
ips_prefix_idx = _nm_utils_ascii_str_to_int64(line, 10, 0, G_MAXINT64, -1);
|
||||
|
||||
if (ips_prefix_idx < 0)
|
||||
continue;
|
||||
|
||||
|
|
@ -252,7 +255,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
|
|||
gs_free const char *uri = NULL;
|
||||
char buf[100];
|
||||
|
||||
iface_data->n_ips_prefix_pending++;
|
||||
iface_data->n_iface_data_pending++;
|
||||
|
||||
nm_http_client_poll_get(
|
||||
NM_HTTP_CLIENT(source),
|
||||
|
|
@ -275,13 +278,13 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
|
|||
}
|
||||
|
||||
iface_data->iface_get_config->ipv4s_len = 0;
|
||||
iface_data->iface_get_config->ipv4s_arr = g_new(in_addr_t, iface_data->n_ips_prefix_pending);
|
||||
iface_data->iface_get_config->ipv4s_arr = g_new(in_addr_t, iface_data->n_iface_data_pending);
|
||||
|
||||
{
|
||||
gs_free const char *uri = NULL;
|
||||
char buf[30];
|
||||
|
||||
iface_data->n_ips_prefix_pending++;
|
||||
iface_data->n_iface_data_pending++;
|
||||
nm_http_client_poll_get(
|
||||
NM_HTTP_CLIENT(source),
|
||||
(uri = _azure_uri_interfaces(
|
||||
|
|
@ -336,25 +339,24 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|||
goto out_done;
|
||||
}
|
||||
|
||||
if (!g_hash_table_lookup_extended(get_config_data->result_dict,
|
||||
v_hwaddr,
|
||||
(gpointer *) &iface_data->hwaddr,
|
||||
(gpointer *) &iface_data->iface_get_config)) {
|
||||
iface_data->iface_get_config = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
||||
|
||||
if (!iface_data->iface_get_config) {
|
||||
if (!get_config_data->any) {
|
||||
_LOGD("get-config: skip fetching meta data for %s (%" G_GSSIZE_FORMAT ")",
|
||||
v_hwaddr,
|
||||
iface_data->intern_iface_idx);
|
||||
goto out_done;
|
||||
}
|
||||
iface_data->iface_get_config = nmcs_provider_get_config_iface_data_new(FALSE);
|
||||
g_hash_table_insert(get_config_data->result_dict,
|
||||
(char *) (iface_data->hwaddr = g_steal_pointer(&v_hwaddr)),
|
||||
iface_data->iface_get_config);
|
||||
iface_data->iface_get_config =
|
||||
nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
|
||||
FALSE,
|
||||
v_hwaddr);
|
||||
} else {
|
||||
if (iface_data->iface_get_config->iface_idx >= 0) {
|
||||
_LOGI("interface[%" G_GSSIZE_FORMAT "]: duplicate MAC address %s returned",
|
||||
iface_data->intern_iface_idx,
|
||||
iface_data->hwaddr);
|
||||
iface_data->iface_get_config->hwaddr);
|
||||
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
|
||||
"duplicate MAC address for index %" G_GSSIZE_FORMAT,
|
||||
iface_data->intern_iface_idx);
|
||||
|
|
@ -366,7 +368,7 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|||
|
||||
_LOGD("interface[%" G_GSSIZE_FORMAT "]: found a matching device with hwaddr %s",
|
||||
iface_data->intern_iface_idx,
|
||||
iface_data->hwaddr);
|
||||
iface_data->iface_get_config->hwaddr);
|
||||
|
||||
nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT "/ipv4/ipAddress/", iface_data->intern_iface_idx);
|
||||
|
||||
|
|
@ -445,8 +447,7 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
|
|||
.iface_get_config = NULL,
|
||||
.intern_iface_idx = intern_iface_idx,
|
||||
.extern_iface_idx = extern_iface_idx_cnt++,
|
||||
.n_ips_prefix_pending = 0,
|
||||
.hwaddr = NULL,
|
||||
.n_iface_data_pending = 0,
|
||||
};
|
||||
g_ptr_array_add(ifaces_arr, iface_data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,14 +136,13 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
|
|||
gboolean is_local_ipv4)
|
||||
{
|
||||
NMCSProviderGetConfigTaskData *get_config_data;
|
||||
const char * hwaddr = NULL;
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
gs_free_error GError * error = NULL;
|
||||
NMCSProviderGetConfigIfaceData *config_iface_data;
|
||||
in_addr_t tmp_addr;
|
||||
int tmp_prefix;
|
||||
|
||||
nm_utils_user_data_unpack(user_data, &get_config_data, &hwaddr);
|
||||
nm_utils_user_data_unpack(user_data, &get_config_data, &config_iface_data);
|
||||
|
||||
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
|
||||
|
||||
|
|
@ -153,8 +152,6 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
|
|||
if (error)
|
||||
goto out;
|
||||
|
||||
config_iface_data = g_hash_table_lookup(get_config_data->result_dict, hwaddr);
|
||||
|
||||
if (is_local_ipv4) {
|
||||
gs_free const char **s_addrs = NULL;
|
||||
gsize i, len;
|
||||
|
|
@ -250,22 +247,20 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|||
NMCSProviderGetConfigIfaceData *config_iface_data;
|
||||
gs_free char * uri1 = NULL;
|
||||
gs_free char * uri2 = NULL;
|
||||
const char * hwaddr;
|
||||
|
||||
if (!g_hash_table_lookup_extended(get_config_data->result_dict,
|
||||
v_hwaddr,
|
||||
(gpointer *) &hwaddr,
|
||||
(gpointer *) &config_iface_data)) {
|
||||
config_iface_data = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
||||
|
||||
if (!config_iface_data) {
|
||||
if (!get_config_data->any) {
|
||||
_LOGD("get-config: skip fetching meta data for %s (%s)",
|
||||
v_hwaddr,
|
||||
v_mac_data->path);
|
||||
continue;
|
||||
}
|
||||
config_iface_data = nmcs_provider_get_config_iface_data_new(FALSE);
|
||||
g_hash_table_insert(get_config_data->result_dict,
|
||||
(char *) (hwaddr = g_strdup(v_hwaddr)),
|
||||
config_iface_data);
|
||||
config_iface_data =
|
||||
nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
|
||||
FALSE,
|
||||
v_hwaddr);
|
||||
}
|
||||
|
||||
nm_assert(config_iface_data->iface_idx == -1);
|
||||
|
|
@ -274,7 +269,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|||
|
||||
_LOGD("get-config: start fetching meta data for #%" G_GSSIZE_FORMAT ", %s (%s)",
|
||||
config_iface_data->iface_idx,
|
||||
hwaddr,
|
||||
config_iface_data->hwaddr,
|
||||
v_mac_data->path);
|
||||
|
||||
get_config_data->n_pending++;
|
||||
|
|
@ -292,7 +287,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|||
NULL,
|
||||
NULL,
|
||||
_get_config_fetch_done_cb_subnet_ipv4_cidr_block,
|
||||
nm_utils_user_data_pack(get_config_data, hwaddr));
|
||||
nm_utils_user_data_pack(get_config_data, config_iface_data));
|
||||
|
||||
get_config_data->n_pending++;
|
||||
nm_http_client_poll_get(
|
||||
|
|
@ -309,7 +304,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|||
NULL,
|
||||
NULL,
|
||||
_get_config_fetch_done_cb_local_ipv4s,
|
||||
nm_utils_user_data_pack(get_config_data, hwaddr));
|
||||
nm_utils_user_data_pack(get_config_data, config_iface_data));
|
||||
}
|
||||
|
||||
_nmcs_provider_get_config_task_maybe_return(get_config_data, NULL);
|
||||
|
|
|
|||
|
|
@ -247,7 +247,6 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|||
GCPIfaceData * iface_data = user_data;
|
||||
gs_free_error GError * error = NULL;
|
||||
gs_free char * v_hwaddr = NULL;
|
||||
const char * hwaddr = NULL;
|
||||
gs_free const char * uri = NULL;
|
||||
char sbuf[100];
|
||||
NMCSProviderGetConfigTaskData *get_config_data;
|
||||
|
|
@ -273,26 +272,25 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|||
goto out_done;
|
||||
}
|
||||
|
||||
if (!g_hash_table_lookup_extended(get_config_data->result_dict,
|
||||
v_hwaddr,
|
||||
(gpointer *) &hwaddr,
|
||||
(gpointer *) &iface_data->iface_get_config)) {
|
||||
iface_data->iface_get_config = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
||||
|
||||
if (!iface_data->iface_get_config) {
|
||||
if (!get_config_data->any) {
|
||||
_LOGD("get-config: skip fetching meta data for %s (%" G_GSSIZE_FORMAT ")",
|
||||
v_hwaddr,
|
||||
iface_data->intern_iface_idx);
|
||||
goto out_done;
|
||||
}
|
||||
iface_data->iface_get_config = nmcs_provider_get_config_iface_data_new(FALSE);
|
||||
g_hash_table_insert(get_config_data->result_dict,
|
||||
(char *) (hwaddr = g_steal_pointer(&v_hwaddr)),
|
||||
iface_data->iface_get_config);
|
||||
iface_data->iface_get_config =
|
||||
nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
|
||||
FALSE,
|
||||
v_hwaddr);
|
||||
is_requested = FALSE;
|
||||
} else {
|
||||
if (iface_data->iface_get_config->iface_idx >= 0) {
|
||||
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: duplicate MAC address %s returned",
|
||||
iface_data->intern_iface_idx,
|
||||
hwaddr);
|
||||
iface_data->iface_get_config->hwaddr);
|
||||
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
|
||||
"duplicate MAC address for index %" G_GSSIZE_FORMAT,
|
||||
iface_data->intern_iface_idx);
|
||||
|
|
@ -306,7 +304,7 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|||
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: found a %sdevice with hwaddr %s",
|
||||
iface_data->intern_iface_idx,
|
||||
is_requested ? "requested " : "",
|
||||
hwaddr);
|
||||
iface_data->iface_get_config->hwaddr);
|
||||
|
||||
nm_sprintf_buf(sbuf, "%" G_GSSIZE_FORMAT "/forwarded-ips/", iface_data->intern_iface_idx);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,90 @@ nmcs_provider_get_main_context(NMCSProvider *self)
|
|||
|
||||
return nm_http_client_get_main_context(NMCS_PROVIDER_GET_PRIVATE(self)->http_client);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
_result_new_sort_iface_data(gconstpointer pa, gconstpointer pb)
|
||||
{
|
||||
const NMCSProviderGetConfigIfaceData *a = *((const NMCSProviderGetConfigIfaceData *const *) pa);
|
||||
const NMCSProviderGetConfigIfaceData *b = *((const NMCSProviderGetConfigIfaceData *const *) pb);
|
||||
|
||||
/* negative iface_idx are sorted to the end. */
|
||||
NM_CMP_DIRECT((a->iface_idx < 0), (b->iface_idx < 0));
|
||||
|
||||
NM_CMP_FIELD(a, b, iface_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NMCSProviderGetConfigResult *
|
||||
nmcs_provider_get_config_result_new(GHashTable *iface_datas)
|
||||
{
|
||||
const NMCSProviderGetConfigIfaceData *iface_data;
|
||||
NMCSProviderGetConfigResult * result;
|
||||
GHashTableIter h_iter;
|
||||
guint num_valid_ifaces = 0;
|
||||
guint num_ipv4s = 0;
|
||||
GPtrArray * ptrarr;
|
||||
guint n_iface_datas;
|
||||
|
||||
n_iface_datas = g_hash_table_size(iface_datas);
|
||||
|
||||
ptrarr = g_ptr_array_sized_new(n_iface_datas + 1u);
|
||||
|
||||
g_hash_table_iter_init(&h_iter, iface_datas);
|
||||
while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &iface_data)) {
|
||||
if (nmcs_provider_get_config_iface_data_is_valid(iface_data)) {
|
||||
num_valid_ifaces++;
|
||||
num_ipv4s += iface_data->ipv4s_len;
|
||||
}
|
||||
g_ptr_array_add(ptrarr, (gpointer) iface_data);
|
||||
}
|
||||
|
||||
g_ptr_array_sort(ptrarr, _result_new_sort_iface_data);
|
||||
|
||||
nm_assert(n_iface_datas == ptrarr->len);
|
||||
|
||||
g_ptr_array_add(ptrarr, NULL);
|
||||
|
||||
result = g_new(NMCSProviderGetConfigResult, 1);
|
||||
*result = (NMCSProviderGetConfigResult){
|
||||
.iface_datas = g_hash_table_ref(iface_datas),
|
||||
.n_iface_datas = n_iface_datas,
|
||||
.iface_datas_arr =
|
||||
(const NMCSProviderGetConfigIfaceData **) g_ptr_array_free(ptrarr, FALSE),
|
||||
.num_valid_ifaces = num_valid_ifaces,
|
||||
.num_ipv4s = num_ipv4s,
|
||||
};
|
||||
|
||||
#if NM_MORE_ASSERTS > 5
|
||||
{
|
||||
gsize iface_idx_expected = 0;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < result->n_iface_datas; i++) {
|
||||
if (result->iface_datas_arr[i]->iface_idx < 0) {
|
||||
nm_assert(result->iface_datas_arr[i]->iface_idx == -1);
|
||||
iface_idx_expected = -1;
|
||||
continue;
|
||||
}
|
||||
nm_assert(result->iface_datas_arr[i]->iface_idx == iface_idx_expected);
|
||||
iface_idx_expected++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result)
|
||||
{
|
||||
if (result) {
|
||||
nm_g_hash_table_unref(result->iface_datas);
|
||||
g_free((gpointer) result->iface_datas_arr);
|
||||
g_free(result);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -90,15 +174,25 @@ nmcs_provider_detect_finish(NMCSProvider *self, GAsyncResult *result, GError **e
|
|||
/*****************************************************************************/
|
||||
|
||||
NMCSProviderGetConfigIfaceData *
|
||||
nmcs_provider_get_config_iface_data_new(gboolean was_requested)
|
||||
nmcs_provider_get_config_iface_data_create(GHashTable *iface_datas,
|
||||
gboolean was_requested,
|
||||
const char *hwaddr)
|
||||
{
|
||||
NMCSProviderGetConfigIfaceData *iface_data;
|
||||
|
||||
nm_assert(hwaddr);
|
||||
|
||||
iface_data = g_slice_new(NMCSProviderGetConfigIfaceData);
|
||||
*iface_data = (NMCSProviderGetConfigIfaceData){
|
||||
.hwaddr = g_strdup(hwaddr),
|
||||
.iface_idx = -1,
|
||||
.was_requested = was_requested,
|
||||
};
|
||||
|
||||
/* the has does not own the key (iface_datta->hwaddr), the lifetime of the
|
||||
* key is associated with the iface_data instance. */
|
||||
g_hash_table_replace(iface_datas, (char *) iface_data->hwaddr, iface_data);
|
||||
|
||||
return iface_data;
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +203,7 @@ _iface_data_free(gpointer data)
|
|||
|
||||
g_free(iface_data->ipv4s_arr);
|
||||
g_free(iface_data->iproutes_arr);
|
||||
g_free((char *) iface_data->hwaddr);
|
||||
|
||||
nm_g_slice_free(iface_data);
|
||||
}
|
||||
|
|
@ -137,8 +232,8 @@ _get_config_task_maybe_return(NMCSProviderGetConfigTaskData *get_config_data, GE
|
|||
} else {
|
||||
_LOGD("get-config: success");
|
||||
g_task_return_pointer(get_config_data->task,
|
||||
g_hash_table_ref(get_config_data->result_dict),
|
||||
(GDestroyNotify) g_hash_table_unref);
|
||||
nmcs_provider_get_config_result_new(get_config_data->result_dict),
|
||||
(GDestroyNotify) nmcs_provider_get_config_result_free);
|
||||
}
|
||||
|
||||
nm_clear_g_signal_handler(g_task_get_cancellable(get_config_data->task),
|
||||
|
|
@ -187,16 +282,13 @@ nmcs_provider_get_config(NMCSProvider * self,
|
|||
*get_config_data = (NMCSProviderGetConfigTaskData){
|
||||
.task = nm_g_task_new(self, cancellable, nmcs_provider_get_config, callback, user_data),
|
||||
.any = any,
|
||||
.result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _iface_data_free),
|
||||
.result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, _iface_data_free),
|
||||
};
|
||||
|
||||
nmcs_wait_for_objects_register(get_config_data->task);
|
||||
|
||||
for (; hwaddrs && hwaddrs[0]; hwaddrs++) {
|
||||
g_hash_table_insert(get_config_data->result_dict,
|
||||
g_strdup(hwaddrs[0]),
|
||||
nmcs_provider_get_config_iface_data_new(TRUE));
|
||||
}
|
||||
for (; hwaddrs && hwaddrs[0]; hwaddrs++)
|
||||
nmcs_provider_get_config_iface_data_create(get_config_data->result_dict, TRUE, hwaddrs[0]);
|
||||
|
||||
if (cancellable) {
|
||||
gulong cancelled_id;
|
||||
|
|
@ -217,7 +309,7 @@ nmcs_provider_get_config(NMCSProvider * self,
|
|||
NMCS_PROVIDER_GET_CLASS(self)->get_config(self, get_config_data);
|
||||
}
|
||||
|
||||
GHashTable *
|
||||
NMCSProviderGetConfigResult *
|
||||
nmcs_provider_get_config_finish(NMCSProvider *self, GAsyncResult *result, GError **error)
|
||||
{
|
||||
g_return_val_if_fail(NMCS_IS_PROVIDER(self), FALSE);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
/* And it's exactly the same pointer that is also the key for the iface_datas
|
||||
* dictionary. */
|
||||
const char *hwaddr;
|
||||
|
||||
in_addr_t *ipv4s_arr;
|
||||
gsize ipv4s_len;
|
||||
|
||||
|
|
@ -19,9 +23,11 @@ typedef struct {
|
|||
gssize iface_idx;
|
||||
|
||||
in_addr_t cidr_addr;
|
||||
in_addr_t gateway;
|
||||
guint8 cidr_prefix;
|
||||
bool has_ipv4s : 1;
|
||||
bool has_cidr : 1;
|
||||
bool has_gateway : 1;
|
||||
|
||||
NMIPRoute **iproutes_arr;
|
||||
gsize iproutes_len;
|
||||
|
|
@ -39,7 +45,43 @@ nmcs_provider_get_config_iface_data_is_valid(const NMCSProviderGetConfigIfaceDat
|
|||
&& ((config_data->has_ipv4s && config_data->has_cidr) || config_data->iproutes_len);
|
||||
}
|
||||
|
||||
NMCSProviderGetConfigIfaceData *nmcs_provider_get_config_iface_data_new(gboolean was_requested);
|
||||
NMCSProviderGetConfigIfaceData *nmcs_provider_get_config_iface_data_create(GHashTable *iface_datas,
|
||||
gboolean was_requested,
|
||||
const char *hwaddr);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
/* A dictionary of (const char *) -> (NMCSProviderGetConfigIfaceData *).
|
||||
* This is the per-interface result of get_config().
|
||||
*
|
||||
* The key is the same pointer as NMCSProviderGetConfigIfaceData's hwaddr. */
|
||||
GHashTable *iface_datas;
|
||||
|
||||
/* The number of iface_datas that are nmcs_provider_get_config_iface_data_is_valid(). */
|
||||
guint num_valid_ifaces;
|
||||
|
||||
/* the number of IPv4 addresses over all valid iface_datas. */
|
||||
guint num_ipv4s;
|
||||
|
||||
guint n_iface_datas;
|
||||
|
||||
/* The sorted value of @iface_datas, sorted by iface_idx.
|
||||
*
|
||||
* Not found entries (iface_idx == -1) are sorted at the end. */
|
||||
const NMCSProviderGetConfigIfaceData *const *iface_datas_arr;
|
||||
|
||||
} NMCSProviderGetConfigResult;
|
||||
|
||||
void nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result);
|
||||
|
||||
NM_AUTO_DEFINE_FCN0(NMCSProviderGetConfigResult *,
|
||||
_nm_auto_free_nmcs_provider_get_config_result,
|
||||
nmcs_provider_get_config_result_free);
|
||||
#define nm_auto_free_nmcs_provider_get_config_result \
|
||||
nm_auto(_nm_auto_free_nmcs_provider_get_config_result)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GTask *task;
|
||||
|
|
@ -122,7 +164,7 @@ void nmcs_provider_get_config(NMCSProvider * provider,
|
|||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GHashTable *
|
||||
NMCSProviderGetConfigResult *
|
||||
nmcs_provider_get_config_finish(NMCSProvider *provider, GAsyncResult *result, GError **error);
|
||||
|
||||
#endif /* __NMCS_PROVIDER_H__ */
|
||||
|
|
|
|||
|
|
@ -363,6 +363,12 @@ nm_ip_address_equal(NMIPAddress *address, NMIPAddress *other)
|
|||
* Creates a copy of @address
|
||||
*
|
||||
* Returns: (transfer full): a copy of @address
|
||||
*
|
||||
* This API was part of public headers before 1.32.0 but
|
||||
* was erroneously not exported in the ABI. It is thus only
|
||||
* usable since 1.32.0, 1.30.8.
|
||||
*
|
||||
* Since: 1.32, 1.30.8
|
||||
**/
|
||||
NMIPAddress *
|
||||
nm_ip_address_dup(NMIPAddress *address)
|
||||
|
|
@ -820,6 +826,12 @@ nm_ip_route_equal(NMIPRoute *route, NMIPRoute *other)
|
|||
* Creates a copy of @route
|
||||
*
|
||||
* Returns: (transfer full): a copy of @route
|
||||
*
|
||||
* This API was part of public headers before 1.32.0 but
|
||||
* was erroneously not exported in the ABI. It is thus only
|
||||
* usable since 1.32.0, 1.30.8.
|
||||
*
|
||||
* Since: 1.32, 1.30.8
|
||||
**/
|
||||
NMIPRoute *
|
||||
nm_ip_route_dup(NMIPRoute *route)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ gboolean nm_ip_address_equal(NMIPAddress *address, NMIPAddress *other);
|
|||
NM_AVAILABLE_IN_1_22
|
||||
int
|
||||
nm_ip_address_cmp_full(const NMIPAddress *a, const NMIPAddress *b, NMIPAddressCmpFlags cmp_flags);
|
||||
|
||||
NM_AVAILABLE_IN_1_30_8
|
||||
NMIPAddress *nm_ip_address_dup(NMIPAddress *address);
|
||||
|
||||
int nm_ip_address_get_family(NMIPAddress *address);
|
||||
|
|
@ -92,6 +94,7 @@ enum { /*< flags >*/
|
|||
NM_AVAILABLE_IN_1_10
|
||||
gboolean nm_ip_route_equal_full(NMIPRoute *route, NMIPRoute *other, guint cmp_flags);
|
||||
|
||||
NM_AVAILABLE_IN_1_30_8
|
||||
NMIPRoute *nm_ip_route_dup(NMIPRoute *route);
|
||||
|
||||
int nm_ip_route_get_family(NMIPRoute *route);
|
||||
|
|
|
|||
|
|
@ -1787,5 +1787,7 @@ global:
|
|||
|
||||
libnm_1_30_8 {
|
||||
global:
|
||||
nm_ip_address_dup;
|
||||
nm_ip_route_dup;
|
||||
nm_setting_ip_config_get_required_timeout;
|
||||
} libnm_1_30_0;
|
||||
|
|
|
|||
|
|
@ -221,7 +221,9 @@
|
|||
Also, if the device is currently not activated in NetworkManager or if the currently
|
||||
activated profile has a user-data <literal>org.freedesktop.nm-cloud-setup.skip=yes</literal>,
|
||||
it is skipped.</para>
|
||||
<para>Then, the tool will change the runtime configuration of the device.
|
||||
<para>If only one interface and one address is configured, then the tool does nothing
|
||||
and leaves the automatic configuration that was obtained via DHCP.</para>
|
||||
<para>Otherwise, the tool will change the runtime configuration of the device.
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Add static IPv4 addresses for all the configured addresses from <literal>local-ipv4s</literal> with
|
||||
|
|
@ -232,15 +234,25 @@
|
|||
<para>Choose a route table 30400 + the index of the interface and
|
||||
add a default route <literal>0.0.0.0/0</literal>. The gateway
|
||||
is the first IP address in the CIDR subnet block. For
|
||||
example, we might get a route <literal>"0.0.0.0/0 172.16.5.1 10 table=30401"</literal>.</para>
|
||||
example, we might get a route <literal>"0.0.0.0/0 172.16.5.1 10 table=30400"</literal>.</para>
|
||||
<para>Also choose a route table 30200 + the interface index. This
|
||||
contains a direct routes to the subnets of this interface.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Finally, add a policy routing rule for each address. For example
|
||||
<literal>"priority 30401 from 172.16.5.3/32 table 30401, priority 30401 from 172.16.5.4/32 table 30401"</literal>.</para>
|
||||
<literal>"priority 30200 from 172.16.5.3/32 table 30200, priority 30200 from 172.16.5.4/32 table 30200"</literal>.
|
||||
and
|
||||
<literal>"priority 30400 from 172.16.5.3/32 table 30400, priority 30400 from 172.16.5.4/32 table 30400"</literal>
|
||||
The 30200+ rules select the table to reach the subnet directly, while the 30400+ rules use the
|
||||
default route. Also add a rule
|
||||
<literal>"priority 30350 table main suppress_prefixlength 0"</literal>. This has a priority between
|
||||
the two previous rules and causes a lookup of routes in the main table while ignoring the default
|
||||
route. The purpose of this is so that other specific routes in the main table are honored over
|
||||
the default route in table 30400+.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
With above example, this roughly corresponds for interface <literal>eth0</literal> to
|
||||
<command>nmcli device modify "eth0" ipv4.addresses "172.16.5.3/24,172.16.5.4/24" ipv4.routes "0.0.0.0/0 172.16.5.1 10 table=30401" ipv4.routing-rules "priority 30401 from 172.16.5.3/32 table 30401, priority 30401 from 172.16.5.4/32 table 30401"</command>.
|
||||
<command>nmcli device modify "eth0" ipv4.addresses "172.16.5.3/24,172.16.5.4/24" ipv4.routes "172.16.5.0/24 0.0.0.0 10 table=30200, 0.0.0.0/0 172.16.5.1 10 table=30400" ipv4.routing-rules "priority 30200 from 172.16.5.3/32 table 30200, priority 30200 from 172.16.5.4/32 table 30200, priority 20350 table main suppress_prefixlength 0, priority 30400 from 172.16.5.3/32 table 30400, priority 30400 from 172.16.5.4/32 table 30400"</command>.
|
||||
Note that this replaces the previous addresses, routes and rules with the new information.
|
||||
But also note that this only changes the run time configuration of the device. The
|
||||
connection profile on disk is not affected.
|
||||
|
|
@ -323,14 +335,8 @@
|
|||
</listitem>
|
||||
<listitem>
|
||||
<para>At this point, we have a list of all interfaces (by MAC address) and their configured IPv4 addresses.</para>
|
||||
<para>For each device, we lookup the currently applied connection in NetworkManager. That implies, that the device is currently activated
|
||||
in NetworkManager. If no such device was in NetworkManager, or if the profile has user-data <literal>org.freedesktop.nm-cloud-setup.skip=yes</literal>,
|
||||
we skip the device. Now for each found IP address we add a static address "$ADDR/$SUBNET_PREFIX". Also we configure policy routing
|
||||
by adding a static route "$ADDR/$SUBNET_PREFIX $GATEWAY 10, table=$TABLE" where $GATEWAY is the first IP address in the subnet and table
|
||||
is 30400 plus the interface index. Also we add a policy routing rule "priority $TABLE from $ADDR/32 table $TABLE".</para>
|
||||
<para>The effect is not unlike calling
|
||||
<command>nmcli device modify "$DEVICE" ipv4.addresses "$ADDR/$SUBNET [,...]" ipv4.routes "$ADDR/32 $GATEWAY 10 table=$TABLE" ipv4.routing-rules "priority $TABLE from $ADDR/32 table $TABLE"</command>
|
||||
for all relevant devices and all found addresses.</para>
|
||||
<para>Then the tool configures the system like doing for AWS environment. That is, using source based policy routing
|
||||
with the tables/rules 30200/30400.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</refsect2>
|
||||
|
|
|
|||
|
|
@ -1383,6 +1383,45 @@ _nm_utils_ascii_str_to_uint64(const char *str,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
gint64
|
||||
_nm_utils_ascii_str_to_int64_bin(const char *str,
|
||||
gssize len,
|
||||
guint base,
|
||||
gint64 min,
|
||||
gint64 max,
|
||||
gint64 fallback)
|
||||
{
|
||||
gs_free char *str_clone = NULL;
|
||||
|
||||
/* This is like _nm_utils_ascii_str_to_int64(), but the user may provide
|
||||
* an optional string length, in which case str is not assumed to be NUL
|
||||
* terminated. In that case, any NUL characters inside the first len characters
|
||||
* lead to a failure, except one last NUL character is allowed. */
|
||||
|
||||
if (len >= 0) {
|
||||
gsize l = len;
|
||||
|
||||
nm_assert(l == 0 || str);
|
||||
|
||||
if (l > 0 && str[l - 1u] == '\0') {
|
||||
/* we accept one '\0' at the end of the string. */
|
||||
l--;
|
||||
}
|
||||
|
||||
if (l > 0 && memchr(str, '\0', l)) {
|
||||
/* but we don't accept other NUL characters in the middle. */
|
||||
errno = EINVAL;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
str = nm_strndup_a(300, str, len, &str_clone);
|
||||
}
|
||||
|
||||
return _nm_utils_ascii_str_to_int64(str, base, min, max, fallback);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
nm_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -760,6 +760,13 @@ guint64 _nm_utils_ascii_str_to_uint64(const char *str,
|
|||
guint64 max,
|
||||
guint64 fallback);
|
||||
|
||||
gint64 _nm_utils_ascii_str_to_int64_bin(const char *str,
|
||||
gssize len,
|
||||
guint base,
|
||||
gint64 min,
|
||||
gint64 max,
|
||||
gint64 fallback);
|
||||
|
||||
int _nm_utils_ascii_str_to_bool(const char *str, int default_value);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue