|
Packit Service |
b23acc |
// SPDX-License-Identifier: LGPL-2.1+
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#include "nm-default.h"
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#include "nm-libnm-aux/nm-libnm-aux.h"
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#include "nm-cloud-setup-utils.h"
|
|
Packit Service |
b23acc |
#include "nmcs-provider-ec2.h"
|
|
Packit Service |
b23acc |
#include "nmcs-provider-gcp.h"
|
|
Packit Service |
b23acc |
#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
typedef struct {
|
|
Packit Service |
b23acc |
GMainLoop *main_loop;
|
|
Packit Service |
b23acc |
GCancellable *cancellable;
|
|
Packit Service |
b23acc |
NMCSProvider *provider_result;
|
|
Packit Service |
b23acc |
guint detect_count;
|
|
Packit Service |
b23acc |
} ProviderDetectData;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static void
|
|
Packit Service |
b23acc |
_provider_detect_cb (GObject *source,
|
|
Packit Service |
b23acc |
GAsyncResult *result,
|
|
Packit Service |
b23acc |
gpointer user_data)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
gs_unref_object NMCSProvider *provider = NMCS_PROVIDER (source);
|
|
Packit Service |
b23acc |
gs_free_error GError *error = NULL;
|
|
Packit Service |
b23acc |
ProviderDetectData *dd;
|
|
Packit Service |
b23acc |
gboolean success;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
success = nmcs_provider_detect_finish (provider, result, &error);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (success != (!!error));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (nm_utils_error_is_cancelled (error))
|
|
Packit Service |
b23acc |
return;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
dd = user_data;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (dd->detect_count > 0);
|
|
Packit Service |
b23acc |
dd->detect_count--;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (error) {
|
|
Packit Service |
b23acc |
_LOGI ("provider %s not detected: %s", nmcs_provider_get_name (provider), error->message);
|
|
Packit Service |
b23acc |
if (dd->detect_count > 0) {
|
|
Packit Service |
b23acc |
/* wait longer. */
|
|
Packit Service |
b23acc |
return;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_LOGI ("no provider detected");
|
|
Packit Service |
b23acc |
goto done;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_LOGI ("provider %s detected", nmcs_provider_get_name (provider));
|
|
Packit Service |
b23acc |
dd->provider_result = g_steal_pointer (&provider);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
done:
|
|
Packit Service |
b23acc |
g_cancellable_cancel (dd->cancellable);
|
|
Packit Service |
b23acc |
g_main_loop_quit (dd->main_loop);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static void
|
|
Packit Service |
b23acc |
_provider_detect_sigterm_cb (GCancellable *source,
|
|
Packit Service |
b23acc |
gpointer user_data)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
ProviderDetectData *dd = user_data;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_cancellable_cancel (dd->cancellable);
|
|
Packit Service |
b23acc |
g_clear_object (&dd->provider_result);
|
|
Packit Service |
b23acc |
dd->detect_count = 0;
|
|
Packit Service |
b23acc |
g_main_loop_quit (dd->main_loop);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static NMCSProvider *
|
|
Packit Service |
b23acc |
_provider_detect (GCancellable *sigterm_cancellable)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new (NULL, FALSE);
|
|
Packit Service |
b23acc |
gs_unref_object GCancellable *cancellable = g_cancellable_new ();
|
|
Packit Service |
b23acc |
gs_unref_object NMHttpClient *http_client = NULL;
|
|
Packit Service |
b23acc |
ProviderDetectData dd = {
|
|
Packit Service |
b23acc |
.cancellable = cancellable,
|
|
Packit Service |
b23acc |
.main_loop = main_loop,
|
|
Packit Service |
b23acc |
.detect_count = 0,
|
|
Packit Service |
b23acc |
.provider_result = NULL,
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
const GType gtypes[] = {
|
|
Packit Service |
b23acc |
NMCS_TYPE_PROVIDER_EC2,
|
|
Packit Service |
b23acc |
NMCS_TYPE_PROVIDER_GCP,
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
int i;
|
|
Packit Service |
b23acc |
gulong cancellable_signal_id;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
cancellable_signal_id = g_cancellable_connect (sigterm_cancellable,
|
|
Packit Service |
b23acc |
G_CALLBACK (_provider_detect_sigterm_cb),
|
|
Packit Service |
b23acc |
&dd,
|
|
Packit Service |
b23acc |
NULL);
|
|
Packit Service |
b23acc |
if (!cancellable_signal_id)
|
|
Packit Service |
b23acc |
goto out;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
http_client = nmcs_wait_for_objects_register (nm_http_client_new ());
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
for (i = 0; i < G_N_ELEMENTS (gtypes); i++) {
|
|
Packit Service |
b23acc |
NMCSProvider *provider;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
provider = g_object_new (gtypes[i],
|
|
Packit Service |
b23acc |
NMCS_PROVIDER_HTTP_CLIENT, http_client,
|
|
Packit Service |
b23acc |
NULL);
|
|
Packit Service |
b23acc |
nmcs_wait_for_objects_register (provider);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_LOGD ("start detecting %s provider...", nmcs_provider_get_name (provider));
|
|
Packit Service |
b23acc |
dd.detect_count++;
|
|
Packit Service |
b23acc |
nmcs_provider_detect (provider,
|
|
Packit Service |
b23acc |
cancellable,
|
|
Packit Service |
b23acc |
_provider_detect_cb,
|
|
Packit Service |
b23acc |
&dd);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (dd.detect_count > 0)
|
|
Packit Service |
b23acc |
g_main_loop_run (main_loop);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
out:
|
|
Packit Service |
b23acc |
nm_clear_g_signal_handler (sigterm_cancellable, &cancellable_signal_id);
|
|
Packit Service |
b23acc |
return dd.provider_result;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static char **
|
|
Packit Service |
b23acc |
_nmc_get_hwaddrs (NMClient *nmc)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
gs_unref_ptrarray GPtrArray *hwaddrs = NULL;
|
|
Packit Service |
b23acc |
const GPtrArray *devices;
|
|
Packit Service |
b23acc |
char **hwaddrs_v;
|
|
Packit Service |
b23acc |
gs_free char *str = NULL;
|
|
Packit Service |
b23acc |
guint i;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
devices = nm_client_get_devices (nmc);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
for (i = 0; i < devices->len; i++) {
|
|
Packit Service |
b23acc |
NMDevice *device = devices->pdata[i];
|
|
Packit Service |
b23acc |
const char *hwaddr;
|
|
Packit Service |
b23acc |
char *s;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!NM_IS_DEVICE_ETHERNET (device))
|
|
Packit Service |
b23acc |
continue;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (nm_device_get_state (device) < NM_DEVICE_STATE_UNAVAILABLE)
|
|
Packit Service |
b23acc |
continue;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
hwaddr = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device));
|
|
Packit Service |
b23acc |
if (!hwaddr)
|
|
Packit Service |
b23acc |
continue;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
s = nmcs_utils_hwaddr_normalize (hwaddr, -1);
|
|
Packit Service |
b23acc |
if (!s)
|
|
Packit Service |
b23acc |
continue;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!hwaddrs)
|
|
Packit Service |
b23acc |
hwaddrs = g_ptr_array_new_with_free_func (g_free);
|
|
Packit Service |
b23acc |
g_ptr_array_add (hwaddrs, s);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!hwaddrs) {
|
|
Packit Service |
b23acc |
_LOGD ("found interfaces: none");
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_ptr_array_add (hwaddrs, NULL);
|
|
Packit Service |
b23acc |
hwaddrs_v = (char **) g_ptr_array_free (g_steal_pointer (&hwaddrs), FALSE);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_LOGD ("found interfaces: %s", (str = g_strjoinv (", ", hwaddrs_v)));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return hwaddrs_v;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static NMDevice *
|
|
Packit Service |
b23acc |
_nmc_get_device_by_hwaddr (NMClient *nmc,
|
|
Packit Service |
b23acc |
const char *hwaddr)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const GPtrArray *devices;
|
|
Packit Service |
b23acc |
guint i;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
devices = nm_client_get_devices (nmc);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
for (i = 0; i < devices->len; i++) {
|
|
Packit Service |
b23acc |
NMDevice *device = devices->pdata[i];
|
|
Packit Service |
b23acc |
const char *hwaddr_dev;
|
|
Packit Service |
b23acc |
gs_free char *s = NULL;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!NM_IS_DEVICE_ETHERNET (device))
|
|
Packit Service |
b23acc |
continue;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
hwaddr_dev = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device));
|
|
Packit Service |
b23acc |
if (!hwaddr_dev)
|
|
Packit Service |
b23acc |
continue;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
s = nmcs_utils_hwaddr_normalize (hwaddr_dev, -1);
|
|
Packit Service |
b23acc |
if (s && nm_streq (s, hwaddr))
|
|
Packit Service |
b23acc |
return device;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
typedef struct {
|
|
Packit Service |
b23acc |
GMainLoop *main_loop;
|
|
Packit Service |
b23acc |
GHashTable *config_dict;
|
|
Packit Service |
b23acc |
} GetConfigData;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static void
|
|
Packit Service |
b23acc |
_get_config_cb (GObject *source,
|
|
Packit Service |
b23acc |
GAsyncResult *result,
|
|
Packit Service |
b23acc |
gpointer user_data)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
GetConfigData *data = user_data;
|
|
Packit Service |
b23acc |
gs_unref_hashtable GHashTable *config_dict = NULL;
|
|
Packit Service |
b23acc |
gs_free_error GError *error = NULL;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
config_dict = nmcs_provider_get_config_finish (NMCS_PROVIDER (source), result, &error);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!config_dict) {
|
|
Packit Service |
b23acc |
if (!nm_utils_error_is_cancelled (error))
|
|
Packit Service |
b23acc |
_LOGI ("failure to get meta data: %s", error->message);
|
|
Packit Service |
b23acc |
} else
|
|
Packit Service |
b23acc |
_LOGD ("meta data received");
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
data->config_dict = g_steal_pointer (&config_dict);
|
|
Packit Service |
b23acc |
g_main_loop_quit (data->main_loop);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static GHashTable *
|
|
Packit Service |
b23acc |
_get_config (GCancellable *sigterm_cancellable,
|
|
Packit Service |
b23acc |
NMCSProvider *provider,
|
|
Packit Service |
b23acc |
NMClient *nmc)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new (NULL, FALSE);
|
|
Packit Service |
b23acc |
GetConfigData data = {
|
|
Packit Service |
b23acc |
.main_loop = main_loop,
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
gs_strfreev char **hwaddrs = NULL;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
hwaddrs = _nmc_get_hwaddrs (nmc);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nmcs_provider_get_config (provider,
|
|
Packit Service |
b23acc |
TRUE,
|
|
Packit Service |
b23acc |
(const char *const*) hwaddrs,
|
|
Packit Service |
b23acc |
sigterm_cancellable,
|
|
Packit Service |
b23acc |
_get_config_cb,
|
|
Packit Service |
b23acc |
&data);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_main_loop_run (main_loop);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return data.config_dict;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static gboolean
|
|
Packit Service |
b23acc |
_nmc_skip_connection (NMConnection *connection)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMSettingUser *s_user;
|
|
Packit Service |
b23acc |
const char *v;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
s_user = NM_SETTING_USER (nm_connection_get_setting (connection, NM_TYPE_SETTING_USER));
|
|
Packit Service |
b23acc |
if (!s_user)
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#define USER_TAG_SKIP "org.freedesktop.nm-cloud-setup.skip"
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (nm_setting_user_check_key (USER_TAG_SKIP, NULL));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
v = nm_setting_user_get_data (s_user, USER_TAG_SKIP);
|
|
Packit Service |
b23acc |
return _nm_utils_ascii_str_to_bool (v, FALSE);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static gboolean
|
|
Packit Service |
b23acc |
_nmc_mangle_connection (NMDevice *device,
|
|
Packit Service |
b23acc |
NMConnection *connection,
|
|
Packit Service |
b23acc |
const NMCSProviderGetConfigIfaceData *config_data,
|
|
Packit Service |
b23acc |
gboolean *out_changed)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMSettingIPConfig *s_ip;
|
|
Packit Service |
b23acc |
gsize i;
|
|
Packit Service |
b23acc |
in_addr_t gateway;
|
|
Packit Service |
b23acc |
gint64 rt_metric;
|
|
Packit Service |
b23acc |
guint32 rt_table;
|
|
Packit Service |
b23acc |
NMIPRoute *route_entry;
|
|
Packit Service |
b23acc |
gboolean addrs_changed = FALSE;
|
|
Packit Service |
b23acc |
gboolean rules_changed = FALSE;
|
|
Packit Service |
b23acc |
gboolean routes_changed = FALSE;
|
|
Packit Service |
b23acc |
gs_unref_ptrarray GPtrArray *addrs_new = NULL;
|
|
Packit Service |
b23acc |
gs_unref_ptrarray GPtrArray *rules_new = NULL;
|
|
Packit Service |
b23acc |
gs_unref_ptrarray GPtrArray *routes_new = NULL;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!nm_streq0 (nm_connection_get_connection_type (connection), NM_SETTING_WIRED_SETTING_NAME))
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
s_ip = nm_connection_get_setting_ip4_config (connection);
|
|
Packit Service |
b23acc |
if (!s_ip)
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
addrs_new = g_ptr_array_new_full (config_data->ipv4s_len,
|
|
Packit Service |
b23acc |
(GDestroyNotify) nm_ip_address_unref);
|
|
Packit Service |
b23acc |
rules_new = g_ptr_array_new_full (config_data->ipv4s_len,
|
|
Packit Service |
b23acc |
(GDestroyNotify) nm_ip_routing_rule_unref);
|
|
Packit Service |
b23acc |
routes_new = g_ptr_array_new_full (config_data->iproutes_len + !!config_data->ipv4s_len,
|
|
Packit Service |
b23acc |
(GDestroyNotify) nm_ip_route_unref);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( config_data->has_ipv4s
|
|
Packit Service |
b23acc |
&& config_data->has_cidr) {
|
|
Packit Service |
b23acc |
for (i = 0; i < config_data->ipv4s_len; i++) {
|
|
Packit Service |
b23acc |
NMIPAddress *entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = nm_ip_address_new_binary (AF_INET,
|
|
Packit Service |
b23acc |
&config_data->ipv4s_arr[i],
|
|
Packit Service |
b23acc |
config_data->cidr_prefix,
|
|
Packit Service |
b23acc |
NULL);
|
|
Packit Service |
b23acc |
if (entry)
|
|
Packit Service |
b23acc |
g_ptr_array_add (addrs_new, entry);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gateway = nm_utils_ip4_address_clear_host_address (config_data->cidr_addr, config_data->cidr_prefix);
|
|
Packit Service |
b23acc |
((guint8 *) &gateway)[3] += 1;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
rt_metric = 10;
|
|
Packit Service |
b23acc |
rt_table = 30400 + config_data->iface_idx;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
route_entry = nm_ip_route_new_binary (AF_INET,
|
|
Packit Service |
b23acc |
&nm_ip_addr_zero,
|
|
Packit Service |
b23acc |
0,
|
|
Packit Service |
b23acc |
&gateway,
|
|
Packit Service |
b23acc |
rt_metric,
|
|
Packit Service |
b23acc |
NULL);
|
|
Packit Service |
b23acc |
nm_ip_route_set_attribute (route_entry,
|
|
Packit Service |
b23acc |
NM_IP_ROUTE_ATTRIBUTE_TABLE,
|
|
Packit Service |
b23acc |
g_variant_new_uint32 (rt_table));
|
|
Packit Service |
b23acc |
g_ptr_array_add (routes_new, route_entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
for (i = 0; i < config_data->ipv4s_len; i++) {
|
|
Packit Service |
b23acc |
NMIPRoutingRule *entry;
|
|
Packit Service |
b23acc |
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = nm_ip_routing_rule_new (AF_INET);
|
|
Packit Service |
b23acc |
nm_ip_routing_rule_set_priority (entry, rt_table);
|
|
Packit Service |
b23acc |
nm_ip_routing_rule_set_from (entry,
|
|
Packit Service |
b23acc |
_nm_utils_inet4_ntop (config_data->ipv4s_arr[i], sbuf),
|
|
Packit Service |
b23acc |
32);
|
|
Packit Service |
b23acc |
nm_ip_routing_rule_set_table (entry, rt_table);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (nm_ip_routing_rule_validate (entry, NULL));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_ptr_array_add (rules_new, entry);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
for (i = 0; i < config_data->iproutes_len; ++i)
|
|
Packit Service |
b23acc |
g_ptr_array_add (routes_new, config_data->iproutes_arr[i]);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (addrs_new->len) {
|
|
Packit Service |
b23acc |
addrs_changed = nmcs_setting_ip_replace_ipv4_addresses (s_ip,
|
|
Packit Service |
b23acc |
(NMIPAddress **) addrs_new->pdata,
|
|
Packit Service |
b23acc |
addrs_new->len);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (routes_new->len) {
|
|
Packit Service |
b23acc |
routes_changed = nmcs_setting_ip_replace_ipv4_routes (s_ip,
|
|
Packit Service |
b23acc |
(NMIPRoute **) routes_new->pdata,
|
|
Packit Service |
b23acc |
routes_new->len);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (rules_new->len) {
|
|
Packit Service |
b23acc |
rules_changed = nmcs_setting_ip_replace_ipv4_rules (s_ip,
|
|
Packit Service |
b23acc |
(NMIPRoutingRule **) rules_new->pdata,
|
|
Packit Service |
b23acc |
rules_new->len);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_changed, addrs_changed
|
|
Packit Service |
b23acc |
|| routes_changed
|
|
Packit Service |
b23acc |
|| rules_changed);
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static guint
|
|
Packit Service |
b23acc |
_config_data_get_num_valid (GHashTable *config_dict)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMCSProviderGetConfigIfaceData *config_data;
|
|
Packit Service |
b23acc |
GHashTableIter h_iter;
|
|
Packit Service |
b23acc |
guint n = 0;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_hash_table_iter_init (&h_iter, config_dict);
|
|
Packit Service |
b23acc |
while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &config_data)) {
|
|
Packit Service |
b23acc |
if (nmcs_provider_get_config_iface_data_is_valid (config_data))
|
|
Packit Service |
b23acc |
n++;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return n;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static gboolean
|
|
Packit Service |
b23acc |
_config_one (GCancellable *sigterm_cancellable,
|
|
Packit Service |
b23acc |
NMClient *nmc,
|
|
Packit Service |
b23acc |
gboolean is_single_nic,
|
|
Packit Service |
b23acc |
const char *hwaddr,
|
|
Packit Service |
b23acc |
const NMCSProviderGetConfigIfaceData *config_data)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
gs_unref_object NMDevice *device = NULL;
|
|
Packit Service |
b23acc |
gs_unref_object NMConnection *applied_connection = NULL;
|
|
Packit Service |
b23acc |
guint64 applied_version_id;
|
|
Packit Service |
b23acc |
gs_free_error GError *error = NULL;
|
|
Packit Service |
b23acc |
gboolean changed;
|
|
Packit Service |
b23acc |
gboolean version_id_changed;
|
|
Packit Service |
b23acc |
guint try_count;
|
|
Packit Service |
b23acc |
gboolean any_changes = FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_main_context_iteration (NULL, FALSE);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (g_cancellable_is_cancelled (sigterm_cancellable))
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
device = nm_g_object_ref (_nmc_get_device_by_hwaddr (nmc, hwaddr));
|
|
Packit Service |
b23acc |
if (!device) {
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: skip because device not found", hwaddr);
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!nmcs_provider_get_config_iface_data_is_valid (config_data)) {
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: skip because meta data not successfully fetched", hwaddr);
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: configuring \"%s\" (%s)...",
|
|
Packit Service |
b23acc |
hwaddr,
|
|
Packit Service |
b23acc |
nm_device_get_iface (device) ?: "/unknown/",
|
|
Packit Service |
b23acc |
nm_object_get_path (NM_OBJECT (device)));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
try_count = 0;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
try_again:
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
applied_connection = nmcs_device_get_applied_connection (device,
|
|
Packit Service |
b23acc |
sigterm_cancellable,
|
|
Packit Service |
b23acc |
&applied_version_id,
|
|
Packit Service |
b23acc |
&error);
|
|
Packit Service |
b23acc |
if (!applied_connection) {
|
|
Packit Service |
b23acc |
if (!nm_utils_error_is_cancelled (error))
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: device has no applied connection (%s). Skip", hwaddr, error->message);
|
|
Packit Service |
b23acc |
return any_changes;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (_nmc_skip_connection (applied_connection)) {
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: skip applied connection due to user data %s", hwaddr, USER_TAG_SKIP);
|
|
Packit Service |
b23acc |
return any_changes;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!_nmc_mangle_connection (device,
|
|
Packit Service |
b23acc |
applied_connection,
|
|
Packit Service |
b23acc |
config_data,
|
|
Packit Service |
b23acc |
&changed)) {
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: device has no suitable applied connection. Skip", hwaddr);
|
|
Packit Service |
b23acc |
return any_changes;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!changed) {
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: device needs no update to applied connection \"%s\" (%s). Skip",
|
|
Packit Service |
b23acc |
hwaddr,
|
|
Packit Service |
b23acc |
nm_connection_get_id (applied_connection),
|
|
Packit Service |
b23acc |
nm_connection_get_uuid (applied_connection));
|
|
Packit Service |
b23acc |
return any_changes;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: reapply connection \"%s\" (%s)",
|
|
Packit Service |
b23acc |
hwaddr,
|
|
Packit Service |
b23acc |
nm_connection_get_id (applied_connection),
|
|
Packit Service |
b23acc |
nm_connection_get_uuid (applied_connection));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* we are about to call Reapply(). If if that fails, it counts as if we changed something. */
|
|
Packit Service |
b23acc |
any_changes = TRUE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!nmcs_device_reapply (device,
|
|
Packit Service |
b23acc |
sigterm_cancellable,
|
|
Packit Service |
b23acc |
applied_connection,
|
|
Packit Service |
b23acc |
applied_version_id,
|
|
Packit Service |
b23acc |
&version_id_changed,
|
|
Packit Service |
b23acc |
&error)) {
|
|
Packit Service |
b23acc |
if ( version_id_changed
|
|
Packit Service |
b23acc |
&& try_count < 5) {
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: applied connection changed in the meantime. Retry...",
|
|
Packit Service |
b23acc |
hwaddr);
|
|
Packit Service |
b23acc |
g_clear_object (&applied_connection);
|
|
Packit Service |
b23acc |
g_clear_error (&error);
|
|
Packit Service |
b23acc |
try_count++;
|
|
Packit Service |
b23acc |
goto try_again;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!nm_utils_error_is_cancelled (error)) {
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: failure to reapply connection \"%s\" (%s): %s",
|
|
Packit Service |
b23acc |
hwaddr,
|
|
Packit Service |
b23acc |
nm_connection_get_id (applied_connection),
|
|
Packit Service |
b23acc |
nm_connection_get_uuid (applied_connection),
|
|
Packit Service |
b23acc |
error->message);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
return any_changes;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_LOGD ("config device %s: connection \"%s\" (%s) reapplied",
|
|
Packit Service |
b23acc |
hwaddr,
|
|
Packit Service |
b23acc |
nm_connection_get_id (applied_connection),
|
|
Packit Service |
b23acc |
nm_connection_get_uuid (applied_connection));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return any_changes;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static gboolean
|
|
Packit Service |
b23acc |
_config_all (GCancellable *sigterm_cancellable,
|
|
Packit Service |
b23acc |
NMClient *nmc,
|
|
Packit Service |
b23acc |
GHashTable *config_dict)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
GHashTableIter h_iter;
|
|
Packit Service |
b23acc |
const NMCSProviderGetConfigIfaceData *c_config_data;
|
|
Packit Service |
b23acc |
const char *c_hwaddr;
|
|
Packit Service |
b23acc |
gboolean is_single_nic;
|
|
Packit Service |
b23acc |
gboolean any_changes = FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
is_single_nic = (_config_data_get_num_valid (config_dict) <= 1);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_hash_table_iter_init (&h_iter, config_dict);
|
|
Packit Service |
b23acc |
while (g_hash_table_iter_next (&h_iter, (gpointer *) &c_hwaddr, (gpointer *) &c_config_data)) {
|
|
Packit Service |
b23acc |
if (_config_one (sigterm_cancellable, nmc, is_single_nic, c_hwaddr, c_config_data))
|
|
Packit Service |
b23acc |
any_changes = TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return any_changes;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static gboolean
|
|
Packit Service |
b23acc |
sigterm_handler (gpointer user_data)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
GCancellable *sigterm_cancellable = user_data;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!g_cancellable_is_cancelled (sigterm_cancellable)) {
|
|
Packit Service |
b23acc |
_LOGD ("SIGTERM received");
|
|
Packit Service |
b23acc |
g_cancellable_cancel (user_data);
|
|
Packit Service |
b23acc |
} else
|
|
Packit Service |
b23acc |
_LOGD ("SIGTERM received (again)");
|
|
Packit Service |
b23acc |
return G_SOURCE_CONTINUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
int
|
|
Packit Service |
b23acc |
main (int argc, const char *const*argv)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
gs_unref_object GCancellable *sigterm_cancellable = NULL;
|
|
Packit Service |
b23acc |
nm_auto_destroy_and_unref_gsource GSource *sigterm_source = NULL;
|
|
Packit Service |
b23acc |
gs_unref_object NMCSProvider *provider = NULL;
|
|
Packit Service |
b23acc |
gs_unref_object NMClient *nmc = NULL;
|
|
Packit Service |
b23acc |
gs_unref_hashtable GHashTable *config_dict = NULL;
|
|
Packit Service |
b23acc |
gs_free_error GError *error = NULL;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_nm_logging_enabled_init (g_getenv (NMCS_ENV_VARIABLE ("NM_CLOUD_SETUP_LOG")));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_LOGD ("nm-cloud-setup %s starting...", NM_DIST_VERSION);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (argc != 1) {
|
|
Packit Service |
b23acc |
g_printerr ("%s: no command line arguments supported\n", argv[0]);
|
|
Packit Service |
b23acc |
return EXIT_FAILURE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
sigterm_cancellable = g_cancellable_new ();
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
sigterm_source = nm_g_source_attach (nm_g_unix_signal_source_new (SIGTERM,
|
|
Packit Service |
b23acc |
G_PRIORITY_DEFAULT,
|
|
Packit Service |
b23acc |
sigterm_handler,
|
|
Packit Service |
b23acc |
sigterm_cancellable,
|
|
Packit Service |
b23acc |
NULL),
|
|
Packit Service |
b23acc |
NULL);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
provider = _provider_detect (sigterm_cancellable);
|
|
Packit Service |
b23acc |
if (!provider)
|
|
Packit Service |
b23acc |
goto done;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nmc_client_new_waitsync (sigterm_cancellable,
|
|
Packit Service |
b23acc |
&nmc,
|
|
Packit Service |
b23acc |
&error,
|
|
Packit Service |
b23acc |
NM_CLIENT_INSTANCE_FLAGS, (guint) NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS,
|
|
Packit Service |
b23acc |
NULL);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nmcs_wait_for_objects_register (nmc);
|
|
Packit Service |
b23acc |
nmcs_wait_for_objects_register (nm_client_get_context_busy_watcher (nmc));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (error) {
|
|
Packit Service |
b23acc |
if (!nm_utils_error_is_cancelled (error))
|
|
Packit Service |
b23acc |
_LOGI ("failure to talk to NetworkManager: %s", error->message);
|
|
Packit Service |
b23acc |
goto done;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!nm_client_get_nm_running (nmc)) {
|
|
Packit Service |
b23acc |
_LOGI ("NetworkManager is not running");
|
|
Packit Service |
b23acc |
goto done;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
config_dict = _get_config (sigterm_cancellable, provider, nmc);
|
|
Packit Service |
b23acc |
if (!config_dict)
|
|
Packit Service |
b23acc |
goto done;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (_config_all (sigterm_cancellable, nmc, config_dict))
|
|
Packit Service |
b23acc |
_LOGI ("some changes were applied for provider %s", nmcs_provider_get_name (provider));
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
_LOGD ("no changes were applied for provider %s", nmcs_provider_get_name (provider));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
done:
|
|
Packit Service |
b23acc |
nm_clear_pointer (&config_dict, g_hash_table_unref);
|
|
Packit Service |
b23acc |
g_clear_object (&nmc;;
|
|
Packit Service |
b23acc |
g_clear_object (&provider);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!nmcs_wait_for_objects_iterate_until_done (NULL, 2000)) {
|
|
Packit Service |
b23acc |
_LOGE ("shutdown: timeout waiting to application to quit. This is a bug");
|
|
Packit Service |
b23acc |
nm_assert_not_reached ();
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_clear_g_source_inst (&sigterm_source);
|
|
Packit Service |
b23acc |
g_clear_object (&sigterm_cancellable);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return 0;
|
|
Packit Service |
b23acc |
}
|