2020-12-23 22:21:36 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
2019-11-12 15:54:22 +01:00
|
|
|
|
|
|
|
|
#ifndef __NMCS_PROVIDER_H__
|
|
|
|
|
#define __NMCS_PROVIDER_H__
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "nm-http-client.h"
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2022-04-29 08:29:59 +02:00
|
|
|
struct _NMCSProvider;
|
|
|
|
|
struct _NMCSProviderGetConfigTaskData;
|
|
|
|
|
|
2019-11-12 15:54:22 +01:00
|
|
|
typedef struct {
|
2021-09-01 14:34:51 +02:00
|
|
|
/* And it's exactly the same pointer that is also the key for the iface_datas
|
|
|
|
|
* dictionary. */
|
|
|
|
|
const char *hwaddr;
|
|
|
|
|
|
2022-04-29 08:29:59 +02:00
|
|
|
struct _NMCSProviderGetConfigTaskData *get_config_data;
|
|
|
|
|
|
2019-11-12 15:54:22 +01:00
|
|
|
in_addr_t *ipv4s_arr;
|
|
|
|
|
gsize ipv4s_len;
|
2021-01-05 14:20:48 +01:00
|
|
|
|
|
|
|
|
/* If the interface was seen, get_config() should set this to a
|
|
|
|
|
* unique, increasing, positive index. If the interface is requested,
|
|
|
|
|
* it is initialized to -1. */
|
|
|
|
|
gssize iface_idx;
|
|
|
|
|
|
|
|
|
|
in_addr_t cidr_addr;
|
2021-08-05 07:44:05 -04:00
|
|
|
in_addr_t gateway;
|
2021-01-05 14:20:48 +01:00
|
|
|
guint8 cidr_prefix;
|
|
|
|
|
bool has_ipv4s : 1;
|
|
|
|
|
bool has_cidr : 1;
|
2021-08-05 07:44:05 -04:00
|
|
|
bool has_gateway : 1;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-06-18 18:11:41 +02:00
|
|
|
NMIPRoute **iproutes_arr;
|
|
|
|
|
gsize iproutes_len;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-11-12 15:54:22 +01:00
|
|
|
/* TRUE, if the configuration was requested via hwaddrs argument to
|
|
|
|
|
* nmcs_provider_get_config(). */
|
|
|
|
|
bool was_requested : 1;
|
|
|
|
|
|
2022-04-28 13:56:17 +02:00
|
|
|
/* Usually we would want that the parent class NMCSProvider is not aware about
|
|
|
|
|
* the implementations. However, it's convenient to track implementation specific data
|
|
|
|
|
* here, thus we violate such separation. In practice, all subclasses are known
|
|
|
|
|
* at compile time, and it will be simpler this way. */
|
cloud-setup: use union for NMCSProviderGetConfigIfaceData.priv
Use a union, it makes more sense.
Note that with union, C's struct initialization might not sufficiently
set all fields to the default. In practice yes, but theoretically in C
a NULL pointer and floats must not have all zero bits, so the following
is not guaranteed to work:
struct {
int some_field;
union {
void *v_ptr;
int v_int;
};
} variable = {
.some_field = 24,
};
assert(variable.union.v_ptr == 0);
assert(variable.union.v_int == 0);
When initializing the variable, we should not rely on automatically
initialize all union members correctly. It cannot at the same time
set NULL pointers and zero integers -- well, on our architectures it
probably can, but not as far as guaranteed by C language.
We need to know which union field we are going to use and initialize
it explicitly.
As we know the provider type, we can do that.
Also, maybe in the future we need special free/unref calls when
destroying the type specific data in NMCSProviderGetConfigIfaceData.
As we know the provider, we can.
Note that having type specific data in NMCSProviderGetConfigIfaceData.priv
is a layering violation. But it is still simpler than implementing
type specific handlers (callbacks) or tracking the data somewhere else.
After all, we know at compile time all the existing provider types.
(cherry picked from commit 1e696c7e93c14bc2ea7bfdcf4a655621ceb4e862)
2022-04-29 10:19:54 +02:00
|
|
|
union {
|
2022-04-28 13:56:17 +02:00
|
|
|
struct {
|
|
|
|
|
in_addr_t primary_ip_address;
|
|
|
|
|
bool has_primary_ip_address : 1;
|
|
|
|
|
bool ipv4s_arr_ordered : 1;
|
|
|
|
|
} aliyun;
|
|
|
|
|
} priv;
|
|
|
|
|
|
2019-11-12 15:54:22 +01:00
|
|
|
} NMCSProviderGetConfigIfaceData;
|
|
|
|
|
|
|
|
|
|
static inline gboolean
|
|
|
|
|
nmcs_provider_get_config_iface_data_is_valid(const NMCSProviderGetConfigIfaceData *config_data)
|
|
|
|
|
{
|
|
|
|
|
return config_data && config_data->iface_idx >= 0
|
2020-06-18 18:11:41 +02:00
|
|
|
&& ((config_data->has_ipv4s && config_data->has_cidr) || config_data->iproutes_len);
|
2019-11-12 15:54:22 +01:00
|
|
|
}
|
|
|
|
|
|
2021-09-01 09:30:29 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
/* A dictionary of (const char *) -> (NMCSProviderGetConfigIfaceData *).
|
2021-09-01 14:34:51 +02:00
|
|
|
* This is the per-interface result of get_config().
|
|
|
|
|
*
|
|
|
|
|
* The key is the same pointer as NMCSProviderGetConfigIfaceData's hwaddr. */
|
2021-09-01 09:30:29 +02:00
|
|
|
GHashTable *iface_datas;
|
2021-09-01 09:42:37 +02:00
|
|
|
|
|
|
|
|
/* The number of iface_datas that are nmcs_provider_get_config_iface_data_is_valid(). */
|
|
|
|
|
guint num_valid_ifaces;
|
2021-09-01 10:11:31 +02:00
|
|
|
|
|
|
|
|
/* the number of IPv4 addresses over all valid iface_datas. */
|
|
|
|
|
guint num_ipv4s;
|
2021-09-01 16:59:19 +02:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2021-09-01 09:30:29 +02:00
|
|
|
} 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)
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2022-04-29 08:29:59 +02:00
|
|
|
typedef struct _NMCSProviderGetConfigTaskData {
|
2021-01-04 19:20:14 +01:00
|
|
|
GTask *task;
|
|
|
|
|
|
2022-04-29 08:29:59 +02:00
|
|
|
struct _NMCSProvider *self;
|
|
|
|
|
|
2021-01-04 19:20:14 +01:00
|
|
|
GHashTable *result_dict;
|
|
|
|
|
|
|
|
|
|
/* this cancellable should be used for the provider implementation
|
|
|
|
|
* to listen for cancellation. */
|
|
|
|
|
GCancellable *intern_cancellable;
|
|
|
|
|
|
|
|
|
|
/* the provider implementation may attach extra data. */
|
2019-11-12 15:54:22 +01:00
|
|
|
gpointer extra_data;
|
2021-01-04 19:20:14 +01:00
|
|
|
GDestroyNotify extra_data_destroy;
|
|
|
|
|
|
|
|
|
|
gulong extern_cancelled_id;
|
|
|
|
|
|
|
|
|
|
/* the provider implementation may use this field to track the number of pending
|
|
|
|
|
* operations. */
|
|
|
|
|
guint n_pending;
|
|
|
|
|
|
|
|
|
|
bool any : 1;
|
2019-11-12 15:54:22 +01:00
|
|
|
} NMCSProviderGetConfigTaskData;
|
|
|
|
|
|
2022-04-29 08:29:59 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
NMCSProviderGetConfigIfaceData *
|
|
|
|
|
nmcs_provider_get_config_iface_data_create(NMCSProviderGetConfigTaskData *get_config_data,
|
|
|
|
|
gboolean was_requested,
|
|
|
|
|
const char *hwaddr);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2019-11-12 15:54:22 +01:00
|
|
|
#define NMCS_TYPE_PROVIDER (nmcs_provider_get_type())
|
2022-12-14 16:21:48 +01:00
|
|
|
#define NMCS_PROVIDER(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMCS_TYPE_PROVIDER, NMCSProvider))
|
2019-11-12 15:54:22 +01:00
|
|
|
#define NMCS_PROVIDER_CLASS(klass) \
|
|
|
|
|
(G_TYPE_CHECK_CLASS_CAST((klass), NMCS_TYPE_PROVIDER, NMCSProviderClass))
|
|
|
|
|
#define NMCS_IS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMCS_TYPE_PROVIDER))
|
|
|
|
|
#define NMCS_IS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMCS_TYPE_PROVIDER))
|
|
|
|
|
#define NMCS_PROVIDER_GET_CLASS(obj) \
|
|
|
|
|
(G_TYPE_INSTANCE_GET_CLASS((obj), NMCS_TYPE_PROVIDER, NMCSProviderClass))
|
|
|
|
|
|
|
|
|
|
#define NMCS_PROVIDER_HTTP_CLIENT "http-client"
|
|
|
|
|
|
|
|
|
|
struct _NMCSProviderPrivate;
|
|
|
|
|
|
2022-04-29 08:29:59 +02:00
|
|
|
typedef struct _NMCSProvider {
|
2019-11-12 15:54:22 +01:00
|
|
|
GObject parent;
|
|
|
|
|
struct _NMCSProviderPrivate *_priv;
|
|
|
|
|
} NMCSProvider;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
GObjectClass parent;
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *_name;
|
|
|
|
|
const char *_env_provider_enabled;
|
2019-11-12 15:54:22 +01:00
|
|
|
|
|
|
|
|
void (*detect)(NMCSProvider *self, GTask *task);
|
|
|
|
|
|
|
|
|
|
void (*get_config)(NMCSProvider *self, NMCSProviderGetConfigTaskData *get_config_data);
|
|
|
|
|
|
|
|
|
|
} NMCSProviderClass;
|
|
|
|
|
|
|
|
|
|
GType nmcs_provider_get_type(void);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
const char *nmcs_provider_get_name(NMCSProvider *provider);
|
|
|
|
|
|
|
|
|
|
NMHttpClient *nmcs_provider_get_http_client(NMCSProvider *provider);
|
|
|
|
|
GMainContext *nmcs_provider_get_main_context(NMCSProvider *provider);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2021-11-09 13:28:54 +01:00
|
|
|
void nmcs_provider_detect(NMCSProvider *provider,
|
|
|
|
|
GCancellable *cancellable,
|
2019-11-12 15:54:22 +01:00
|
|
|
GAsyncReadyCallback callback,
|
|
|
|
|
gpointer user_data);
|
|
|
|
|
|
|
|
|
|
gboolean nmcs_provider_detect_finish(NMCSProvider *provider, GAsyncResult *result, GError **error);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2021-01-04 19:20:14 +01:00
|
|
|
void _nmcs_provider_get_config_task_maybe_return(NMCSProviderGetConfigTaskData *get_config_data,
|
2021-11-09 13:28:54 +01:00
|
|
|
GError *error_take);
|
2021-01-04 19:20:14 +01:00
|
|
|
|
2021-11-09 13:28:54 +01:00
|
|
|
void nmcs_provider_get_config(NMCSProvider *provider,
|
2019-11-12 15:54:22 +01:00
|
|
|
gboolean any,
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *const *hwaddrs,
|
|
|
|
|
GCancellable *cancellable,
|
2019-11-12 15:54:22 +01:00
|
|
|
GAsyncReadyCallback callback,
|
|
|
|
|
gpointer user_data);
|
|
|
|
|
|
2021-09-01 09:30:29 +02:00
|
|
|
NMCSProviderGetConfigResult *
|
2019-11-12 15:54:22 +01:00
|
|
|
nmcs_provider_get_config_finish(NMCSProvider *provider, GAsyncResult *result, GError **error);
|
|
|
|
|
|
cloud-setup: use union for NMCSProviderGetConfigIfaceData.priv
Use a union, it makes more sense.
Note that with union, C's struct initialization might not sufficiently
set all fields to the default. In practice yes, but theoretically in C
a NULL pointer and floats must not have all zero bits, so the following
is not guaranteed to work:
struct {
int some_field;
union {
void *v_ptr;
int v_int;
};
} variable = {
.some_field = 24,
};
assert(variable.union.v_ptr == 0);
assert(variable.union.v_int == 0);
When initializing the variable, we should not rely on automatically
initialize all union members correctly. It cannot at the same time
set NULL pointers and zero integers -- well, on our architectures it
probably can, but not as far as guaranteed by C language.
We need to know which union field we are going to use and initialize
it explicitly.
As we know the provider type, we can do that.
Also, maybe in the future we need special free/unref calls when
destroying the type specific data in NMCSProviderGetConfigIfaceData.
As we know the provider, we can.
Note that having type specific data in NMCSProviderGetConfigIfaceData.priv
is a layering violation. But it is still simpler than implementing
type specific handlers (callbacks) or tracking the data somewhere else.
After all, we know at compile time all the existing provider types.
(cherry picked from commit 1e696c7e93c14bc2ea7bfdcf4a655621ceb4e862)
2022-04-29 10:19:54 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/* Forward declare the implemented gtype getters so we can use it at a few places without requiring
|
|
|
|
|
* to include the full header. The other parts of those headers should not be used aside where they
|
|
|
|
|
* are necessary. */
|
|
|
|
|
GType nmcs_provider_aliyun_get_type(void);
|
|
|
|
|
|
2019-11-12 15:54:22 +01:00
|
|
|
#endif /* __NMCS_PROVIDER_H__ */
|