|
Packit Service |
87a54e |
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
Packit |
5756e2 |
/*
|
|
Packit |
5756e2 |
* Copyright (C) 2008 - 2011 Red Hat, Inc.
|
|
Packit |
5756e2 |
*/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-default.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-dispatcher-utils.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-dbus-interface.h"
|
|
Packit |
5756e2 |
#include "nm-connection.h"
|
|
Packit |
5756e2 |
#include "nm-setting-ip4-config.h"
|
|
Packit |
5756e2 |
#include "nm-setting-ip6-config.h"
|
|
Packit |
5756e2 |
#include "nm-setting-connection.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-libnm-core-aux/nm-dispatcher-api.h"
|
|
Packit |
5756e2 |
#include "nm-utils.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/*****************************************************************************/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static gboolean
|
|
Packit Service |
a1bd4f |
_is_valid_key(const char *line, gssize len)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
gsize i, l;
|
|
Packit Service |
a1bd4f |
char ch;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!line)
|
|
Packit Service |
a1bd4f |
return FALSE;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (len < 0)
|
|
Packit Service |
a1bd4f |
len = strlen(line);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (len == 0)
|
|
Packit Service |
a1bd4f |
return FALSE;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
ch = line[0];
|
|
Packit Service |
a1bd4f |
if (!(ch >= 'A' && ch <= 'Z') && !NM_IN_SET(ch, '_'))
|
|
Packit Service |
a1bd4f |
return FALSE;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
l = (gsize) len;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
for (i = 1; i < l; i++) {
|
|
Packit Service |
a1bd4f |
ch = line[i];
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!(ch >= 'A' && ch <= 'Z') && !(ch >= '0' && ch <= '9') && !NM_IN_SET(ch, '_'))
|
|
Packit Service |
a1bd4f |
return FALSE;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
return TRUE;
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static gboolean
|
|
Packit Service |
a1bd4f |
_is_valid_line(const char *line)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
const char *d;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!line)
|
|
Packit Service |
a1bd4f |
return FALSE;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
d = strchr(line, '=');
|
|
Packit Service |
a1bd4f |
if (!d || d == line)
|
|
Packit Service |
a1bd4f |
return FALSE;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
return _is_valid_key(line, d - line);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static char *
|
|
Packit Service |
a1bd4f |
_sanitize_var_name(const char *key)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
char *sanitized;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
nm_assert(key);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!key[0])
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
sanitized = g_ascii_strup(key, -1);
|
|
Packit Service |
a1bd4f |
if (!NM_STRCHAR_ALL(sanitized,
|
|
Packit Service |
a1bd4f |
ch,
|
|
Packit Service |
a1bd4f |
(ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')
|
|
Packit Service |
a1bd4f |
|| NM_IN_SET(ch, '_'))) {
|
|
Packit Service |
a1bd4f |
g_free(sanitized);
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
nm_assert(_is_valid_key(sanitized, -1));
|
|
Packit Service |
a1bd4f |
return sanitized;
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
_items_add_str_take(GPtrArray *items, char *line)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
nm_assert(items);
|
|
Packit Service |
a1bd4f |
nm_assert(_is_valid_line(line));
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
g_ptr_array_add(items, line);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
_items_add_str(GPtrArray *items, const char *line)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
_items_add_str_take(items, g_strdup(line));
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
_items_add_key(GPtrArray *items, const char *prefix, const char *key, const char *value)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
nm_assert(items);
|
|
Packit Service |
a1bd4f |
nm_assert(_is_valid_key(key, -1));
|
|
Packit Service |
a1bd4f |
nm_assert(value);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
_items_add_str_take(items, g_strconcat(prefix ?: "", key, "=", value, NULL));
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
_items_add_key0(GPtrArray *items, const char *prefix, const char *key, const char *value)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
nm_assert(items);
|
|
Packit Service |
a1bd4f |
nm_assert(_is_valid_key(key, -1));
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!value) {
|
|
Packit Service |
a1bd4f |
/* for convenience, allow NULL values to indicate to skip the line. */
|
|
Packit Service |
a1bd4f |
return;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
_items_add_str_take(items, g_strconcat(prefix ?: "", key, "=", value, NULL));
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
G_GNUC_PRINTF(2, 3)
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
_items_add_printf(GPtrArray *items, const char *fmt, ...)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
va_list ap;
|
|
Packit Service |
a1bd4f |
char * line;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
nm_assert(items);
|
|
Packit Service |
a1bd4f |
nm_assert(fmt);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
va_start(ap, fmt);
|
|
Packit Service |
a1bd4f |
line = g_strdup_vprintf(fmt, ap);
|
|
Packit Service |
a1bd4f |
va_end(ap);
|
|
Packit Service |
a1bd4f |
_items_add_str_take(items, line);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
_items_add_strv(GPtrArray *items, const char *prefix, const char *key, const char *const *values)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
gboolean has;
|
|
Packit Service |
a1bd4f |
guint i;
|
|
Packit Service |
a1bd4f |
GString *str;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
nm_assert(items);
|
|
Packit Service |
a1bd4f |
nm_assert(_is_valid_key(key, -1));
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!values || !values[0]) {
|
|
Packit Service |
a1bd4f |
/* Only add an item if the list of @values is not empty */
|
|
Packit Service |
a1bd4f |
return;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
str = g_string_new(NULL);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (prefix)
|
|
Packit Service |
a1bd4f |
g_string_append(str, prefix);
|
|
Packit Service |
a1bd4f |
g_string_append(str, key);
|
|
Packit Service |
a1bd4f |
g_string_append_c(str, '=');
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
has = FALSE;
|
|
Packit Service |
a1bd4f |
for (i = 0; values[i]; i++) {
|
|
Packit Service |
a1bd4f |
if (!values[i][0])
|
|
Packit Service |
a1bd4f |
continue;
|
|
Packit Service |
a1bd4f |
if (has)
|
|
Packit Service |
a1bd4f |
g_string_append_c(str, ' ');
|
|
Packit Service |
a1bd4f |
else
|
|
Packit Service |
a1bd4f |
has = TRUE;
|
|
Packit Service |
a1bd4f |
g_string_append(str, values[i]);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
_items_add_str_take(items, g_string_free(str, FALSE));
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/*****************************************************************************/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
construct_proxy_items(GPtrArray *items, GVariant *proxy_config, const char *prefix)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
GVariant *variant;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
nm_assert(items);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!proxy_config)
|
|
Packit Service |
a1bd4f |
return;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
variant = g_variant_lookup_value(proxy_config, "pac-url", G_VARIANT_TYPE_STRING);
|
|
Packit Service |
a1bd4f |
if (variant) {
|
|
Packit Service |
a1bd4f |
_items_add_key(items, prefix, "PROXY_PAC_URL", g_variant_get_string(variant, NULL));
|
|
Packit Service |
a1bd4f |
g_variant_unref(variant);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
variant = g_variant_lookup_value(proxy_config, "pac-script", G_VARIANT_TYPE_STRING);
|
|
Packit Service |
a1bd4f |
if (variant) {
|
|
Packit Service |
a1bd4f |
_items_add_key(items, prefix, "PROXY_PAC_SCRIPT", g_variant_get_string(variant, NULL));
|
|
Packit Service |
a1bd4f |
g_variant_unref(variant);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
construct_ip_items(GPtrArray *items, int addr_family, GVariant *ip_config, const char *prefix)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
GVariant *val;
|
|
Packit Service |
a1bd4f |
guint i;
|
|
Packit Service |
a1bd4f |
guint nroutes = 0;
|
|
Packit Service |
a1bd4f |
char four_or_six;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!ip_config)
|
|
Packit Service |
a1bd4f |
return;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!prefix)
|
|
Packit Service |
a1bd4f |
prefix = "";
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
four_or_six = nm_utils_addr_family_to_char(addr_family);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
val = g_variant_lookup_value(ip_config,
|
|
Packit Service |
a1bd4f |
"addresses",
|
|
Packit Service |
a1bd4f |
addr_family == AF_INET ? G_VARIANT_TYPE("aau")
|
|
Packit Service |
a1bd4f |
: G_VARIANT_TYPE("a(ayuay)"));
|
|
Packit Service |
a1bd4f |
if (val) {
|
|
Packit Service |
a1bd4f |
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
|
Packit Service |
a1bd4f |
gs_free char * gateway_free = NULL;
|
|
Packit Service |
a1bd4f |
const char * gateway;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (addr_family == AF_INET)
|
|
Packit Service |
a1bd4f |
addresses = nm_utils_ip4_addresses_from_variant(val, &gateway_free);
|
|
Packit Service |
a1bd4f |
else
|
|
Packit Service |
a1bd4f |
addresses = nm_utils_ip6_addresses_from_variant(val, &gateway_free);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
gateway = gateway_free ?: "0.0.0.0";
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (addresses && addresses->len) {
|
|
Packit Service |
a1bd4f |
for (i = 0; i < addresses->len; i++) {
|
|
Packit Service |
a1bd4f |
NMIPAddress *addr = addresses->pdata[i];
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
_items_add_printf(items,
|
|
Packit Service |
a1bd4f |
"%sIP%c_ADDRESS_%d=%s/%d %s",
|
|
Packit Service |
a1bd4f |
prefix,
|
|
Packit Service |
a1bd4f |
four_or_six,
|
|
Packit Service |
a1bd4f |
i,
|
|
Packit Service |
a1bd4f |
nm_ip_address_get_address(addr),
|
|
Packit Service |
a1bd4f |
nm_ip_address_get_prefix(addr),
|
|
Packit Service |
a1bd4f |
gateway);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
_items_add_printf(items,
|
|
Packit Service |
a1bd4f |
"%sIP%c_NUM_ADDRESSES=%u",
|
|
Packit Service |
a1bd4f |
prefix,
|
|
Packit Service |
a1bd4f |
four_or_six,
|
|
Packit Service |
a1bd4f |
addresses->len);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
_items_add_key(items,
|
|
Packit Service |
a1bd4f |
prefix,
|
|
Packit Service |
a1bd4f |
addr_family == AF_INET ? "IP4_GATEWAY" : "IP6_GATEWAY",
|
|
Packit Service |
a1bd4f |
gateway);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
g_variant_unref(val);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
val = g_variant_lookup_value(ip_config,
|
|
Packit Service |
a1bd4f |
"nameservers",
|
|
Packit Service |
a1bd4f |
addr_family == AF_INET ? G_VARIANT_TYPE("au")
|
|
Packit Service |
a1bd4f |
: G_VARIANT_TYPE("aay"));
|
|
Packit Service |
a1bd4f |
if (val) {
|
|
Packit Service |
a1bd4f |
gs_strfreev char **v = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (addr_family == AF_INET)
|
|
Packit Service |
a1bd4f |
v = nm_utils_ip4_dns_from_variant(val);
|
|
Packit Service |
a1bd4f |
else
|
|
Packit Service |
a1bd4f |
v = nm_utils_ip6_dns_from_variant(val);
|
|
Packit Service |
a1bd4f |
_items_add_strv(items,
|
|
Packit Service |
a1bd4f |
prefix,
|
|
Packit Service |
a1bd4f |
addr_family == AF_INET ? "IP4_NAMESERVERS" : "IP6_NAMESERVERS",
|
|
Packit Service |
a1bd4f |
NM_CAST_STRV_CC(v));
|
|
Packit Service |
a1bd4f |
g_variant_unref(val);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
val = g_variant_lookup_value(ip_config, "domains", G_VARIANT_TYPE_STRING_ARRAY);
|
|
Packit Service |
a1bd4f |
if (val) {
|
|
Packit Service |
a1bd4f |
gs_free const char **v = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
v = g_variant_get_strv(val, NULL);
|
|
Packit Service |
a1bd4f |
_items_add_strv(items, prefix, addr_family == AF_INET ? "IP4_DOMAINS" : "IP6_DOMAINS", v);
|
|
Packit Service |
a1bd4f |
g_variant_unref(val);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (addr_family == AF_INET) {
|
|
Packit Service |
a1bd4f |
val = g_variant_lookup_value(ip_config, "wins-servers", G_VARIANT_TYPE("au"));
|
|
Packit Service |
a1bd4f |
if (val) {
|
|
Packit Service |
a1bd4f |
gs_strfreev char **v = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
v = nm_utils_ip4_dns_from_variant(val);
|
|
Packit Service |
a1bd4f |
_items_add_strv(items, prefix, "IP4_WINS_SERVERS", NM_CAST_STRV_CC(v));
|
|
Packit Service |
a1bd4f |
g_variant_unref(val);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
val = g_variant_lookup_value(ip_config,
|
|
Packit Service |
a1bd4f |
"routes",
|
|
Packit Service |
a1bd4f |
addr_family == AF_INET ? G_VARIANT_TYPE("aau")
|
|
Packit Service |
a1bd4f |
: G_VARIANT_TYPE("a(ayuayu)"));
|
|
Packit Service |
a1bd4f |
if (val) {
|
|
Packit Service |
a1bd4f |
gs_unref_ptrarray GPtrArray *routes = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (addr_family == AF_INET)
|
|
Packit Service |
a1bd4f |
routes = nm_utils_ip4_routes_from_variant(val);
|
|
Packit Service |
a1bd4f |
else
|
|
Packit Service |
a1bd4f |
routes = nm_utils_ip6_routes_from_variant(val);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (routes && routes->len > 0) {
|
|
Packit Service |
a1bd4f |
const char *const DEFAULT_GW = addr_family == AF_INET ? "0.0.0.0" : "::";
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
nroutes = routes->len;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
for (i = 0; i < routes->len; i++) {
|
|
Packit Service |
a1bd4f |
NMIPRoute *route = routes->pdata[i];
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
_items_add_printf(items,
|
|
Packit Service |
a1bd4f |
"%sIP%c_ROUTE_%u=%s/%d %s %u",
|
|
Packit Service |
a1bd4f |
prefix,
|
|
Packit Service |
a1bd4f |
four_or_six,
|
|
Packit Service |
a1bd4f |
i,
|
|
Packit Service |
a1bd4f |
nm_ip_route_get_dest(route),
|
|
Packit Service |
a1bd4f |
nm_ip_route_get_prefix(route),
|
|
Packit Service |
a1bd4f |
nm_ip_route_get_next_hop(route) ?: DEFAULT_GW,
|
|
Packit Service |
a1bd4f |
(guint) NM_MAX((gint64) 0, nm_ip_route_get_metric(route)));
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
g_variant_unref(val);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
if (nroutes > 0 || addr_family == AF_INET) {
|
|
Packit Service |
a1bd4f |
/* we also set IP4_NUM_ROUTES=0, but don't do so for addresses and IPv6 routes.
|
|
Packit Service |
a1bd4f |
* Historic reasons. */
|
|
Packit Service |
a1bd4f |
_items_add_printf(items, "%sIP%c_NUM_ROUTES=%u", prefix, four_or_six, nroutes);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
construct_device_dhcp_items(GPtrArray *items, int addr_family, GVariant *dhcp_config)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
GVariantIter iter;
|
|
Packit Service |
a1bd4f |
const char * key;
|
|
Packit Service |
a1bd4f |
GVariant * val;
|
|
Packit Service |
a1bd4f |
char four_or_six;
|
|
Packit Service |
a1bd4f |
gboolean found_unknown_245 = FALSE;
|
|
Packit Service |
a1bd4f |
gs_unref_variant GVariant *private_245_val = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!dhcp_config)
|
|
Packit Service |
a1bd4f |
return;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!g_variant_is_of_type(dhcp_config, G_VARIANT_TYPE_VARDICT))
|
|
Packit Service |
a1bd4f |
return;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
four_or_six = nm_utils_addr_family_to_char(addr_family);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
g_variant_iter_init(&iter, dhcp_config);
|
|
Packit Service |
a1bd4f |
while (g_variant_iter_next(&iter, "{&sv}", &key, &val)) {
|
|
Packit Service |
a1bd4f |
if (g_variant_is_of_type(val, G_VARIANT_TYPE_STRING)) {
|
|
Packit Service |
a1bd4f |
gs_free char *ucased = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
ucased = _sanitize_var_name(key);
|
|
Packit Service |
a1bd4f |
if (ucased) {
|
|
Packit Service |
a1bd4f |
_items_add_printf(items,
|
|
Packit Service |
a1bd4f |
"DHCP%c_%s=%s",
|
|
Packit Service |
a1bd4f |
four_or_six,
|
|
Packit Service |
a1bd4f |
ucased,
|
|
Packit Service |
a1bd4f |
g_variant_get_string(val, NULL));
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* MS Azure sends the server endpoint in the dhcp private
|
|
Packit Service |
a1bd4f |
* option 245. cloud-init searches the Azure server endpoint
|
|
Packit Service |
a1bd4f |
* value looking for the standard dhclient label used for
|
|
Packit Service |
a1bd4f |
* that option, which is "unknown_245".
|
|
Packit Service |
a1bd4f |
* The 11-dhclient script shipped with Fedora and RHEL dhcp
|
|
Packit Service |
a1bd4f |
* package converts our dispatcher environment vars to the
|
|
Packit Service |
a1bd4f |
* dhclient ones (new_<some_option>) and calls dhclient hook
|
|
Packit Service |
a1bd4f |
* scripts.
|
|
Packit Service |
a1bd4f |
* Let's make cloud-init happy and let's duplicate the dhcp
|
|
Packit Service |
a1bd4f |
* option 245 with the legacy name of the default dhclient
|
|
Packit Service |
a1bd4f |
* label also when using the internal client.
|
|
Packit Service |
a1bd4f |
* Note however that the dhclient plugin will have unknown_
|
|
Packit Service |
a1bd4f |
* labels represented as ascii string when possible, falling
|
|
Packit Service |
a1bd4f |
* back to hex string otherwise.
|
|
Packit Service |
a1bd4f |
* private_ labels instead are always in hex string format.
|
|
Packit Service |
a1bd4f |
* This shouldn't affect the MS Azure server endpoint value,
|
|
Packit Service |
a1bd4f |
* as it usually belongs to the 240.0.0.0/4 network and so
|
|
Packit Service |
a1bd4f |
* is always represented as an hex string. Moreover, cloudinit
|
|
Packit Service |
a1bd4f |
* code checks just for an hex value in unknown_245.
|
|
Packit Service |
a1bd4f |
*/
|
|
Packit Service |
a1bd4f |
if (addr_family == AF_INET) {
|
|
Packit Service |
a1bd4f |
if (nm_streq(key, "private_245"))
|
|
Packit Service |
a1bd4f |
private_245_val = g_variant_ref(val);
|
|
Packit Service |
a1bd4f |
else if (nm_streq(key, "unknown_245"))
|
|
Packit Service |
a1bd4f |
found_unknown_245 = true;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
g_variant_unref(val);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (private_245_val != NULL && !found_unknown_245) {
|
|
Packit Service |
a1bd4f |
_items_add_printf(items,
|
|
Packit Service |
a1bd4f |
"DHCP4_UNKNOWN_245=%s",
|
|
Packit Service |
a1bd4f |
g_variant_get_string(private_245_val, NULL));
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/*****************************************************************************/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
char **
|
|
Packit Service |
a1bd4f |
nm_dispatcher_utils_construct_envp(const char * action,
|
|
Packit Service |
a1bd4f |
GVariant * connection_dict,
|
|
Packit Service |
a1bd4f |
GVariant * connection_props,
|
|
Packit Service |
a1bd4f |
GVariant * device_props,
|
|
Packit Service |
a1bd4f |
GVariant * device_proxy_props,
|
|
Packit Service |
a1bd4f |
GVariant * device_ip4_props,
|
|
Packit Service |
a1bd4f |
GVariant * device_ip6_props,
|
|
Packit Service |
a1bd4f |
GVariant * device_dhcp4_props,
|
|
Packit Service |
a1bd4f |
GVariant * device_dhcp6_props,
|
|
Packit Service |
a1bd4f |
const char * connectivity_state,
|
|
Packit Service |
a1bd4f |
const char * vpn_ip_iface,
|
|
Packit Service |
a1bd4f |
GVariant * vpn_proxy_props,
|
|
Packit Service |
a1bd4f |
GVariant * vpn_ip4_props,
|
|
Packit Service |
a1bd4f |
GVariant * vpn_ip6_props,
|
|
Packit Service |
a1bd4f |
char ** out_iface,
|
|
Packit Service |
a1bd4f |
const char **out_error_message)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
const char * iface = NULL;
|
|
Packit Service |
a1bd4f |
const char * ip_iface = NULL;
|
|
Packit Service |
a1bd4f |
const char * uuid = NULL;
|
|
Packit Service |
a1bd4f |
const char * id = NULL;
|
|
Packit Service |
a1bd4f |
const char * path = NULL;
|
|
Packit Service |
a1bd4f |
const char * filename = NULL;
|
|
Packit Service |
a1bd4f |
gboolean external;
|
|
Packit Service |
a1bd4f |
NMDeviceState dev_state = NM_DEVICE_STATE_UNKNOWN;
|
|
Packit Service |
a1bd4f |
GVariant * variant;
|
|
Packit Service |
a1bd4f |
gs_unref_ptrarray GPtrArray *items = NULL;
|
|
Packit Service |
a1bd4f |
const char * error_message_backup;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!out_error_message)
|
|
Packit Service |
a1bd4f |
out_error_message = &error_message_backup;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
g_return_val_if_fail(action != NULL, NULL);
|
|
Packit Service |
a1bd4f |
g_return_val_if_fail(out_iface != NULL, NULL);
|
|
Packit Service |
a1bd4f |
g_return_val_if_fail(*out_iface == NULL, NULL);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
items = g_ptr_array_new_with_free_func(g_free);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Hostname and connectivity changes don't require a device nor contain a connection */
|
|
Packit Service |
a1bd4f |
if (NM_IN_STRSET(action, NMD_ACTION_HOSTNAME, NMD_ACTION_CONNECTIVITY_CHANGE))
|
|
Packit Service |
a1bd4f |
goto done;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Connection properties */
|
|
Packit Service |
a1bd4f |
if (g_variant_lookup(connection_props, NMD_CONNECTION_PROPS_PATH, "&o", &path))
|
|
Packit Service |
a1bd4f |
_items_add_key(items, NULL, "CONNECTION_DBUS_PATH", path);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (g_variant_lookup(connection_props, NMD_CONNECTION_PROPS_EXTERNAL, "b", &external)
|
|
Packit Service |
a1bd4f |
&& external)
|
|
Packit Service |
a1bd4f |
_items_add_str(items, "CONNECTION_EXTERNAL=1");
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (g_variant_lookup(connection_props, NMD_CONNECTION_PROPS_FILENAME, "&s", &filename))
|
|
Packit Service |
a1bd4f |
_items_add_key(items, NULL, "CONNECTION_FILENAME", filename);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Canonicalize the VPN interface name; "" is used when passing it through
|
|
Packit Service |
a1bd4f |
* D-Bus so make sure that's fixed up here.
|
|
Packit Service |
a1bd4f |
*/
|
|
Packit Service |
a1bd4f |
if (vpn_ip_iface && !vpn_ip_iface[0])
|
|
Packit Service |
a1bd4f |
vpn_ip_iface = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!g_variant_lookup(device_props, NMD_DEVICE_PROPS_INTERFACE, "&s", &iface)) {
|
|
Packit Service |
a1bd4f |
*out_error_message = "Missing or invalid required value " NMD_DEVICE_PROPS_INTERFACE "!";
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
if (!*iface)
|
|
Packit Service |
a1bd4f |
iface = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
variant = g_variant_lookup_value(device_props, NMD_DEVICE_PROPS_IP_INTERFACE, NULL);
|
|
Packit Service |
a1bd4f |
if (variant) {
|
|
Packit Service |
a1bd4f |
if (!g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
|
|
Packit Service |
a1bd4f |
*out_error_message = "Invalid value " NMD_DEVICE_PROPS_IP_INTERFACE "!";
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
g_variant_unref(variant);
|
|
Packit Service |
a1bd4f |
(void) g_variant_lookup(device_props, NMD_DEVICE_PROPS_IP_INTERFACE, "&s", &ip_iface);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!g_variant_lookup(device_props, NMD_DEVICE_PROPS_TYPE, "u", NULL)) {
|
|
Packit Service |
a1bd4f |
*out_error_message = "Missing or invalid required value " NMD_DEVICE_PROPS_TYPE "!";
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
variant = g_variant_lookup_value(device_props, NMD_DEVICE_PROPS_STATE, G_VARIANT_TYPE_UINT32);
|
|
Packit Service |
a1bd4f |
if (!variant) {
|
|
Packit Service |
a1bd4f |
*out_error_message = "Missing or invalid required value " NMD_DEVICE_PROPS_STATE "!";
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
dev_state = g_variant_get_uint32(variant);
|
|
Packit Service |
a1bd4f |
g_variant_unref(variant);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!g_variant_lookup(device_props, NMD_DEVICE_PROPS_PATH, "o", NULL)) {
|
|
Packit Service |
a1bd4f |
*out_error_message = "Missing or invalid required value " NMD_DEVICE_PROPS_PATH "!";
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
{
|
|
Packit Service |
a1bd4f |
gs_unref_variant GVariant *con_setting = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
con_setting = g_variant_lookup_value(connection_dict,
|
|
Packit Service |
a1bd4f |
NM_SETTING_CONNECTION_SETTING_NAME,
|
|
Packit Service |
a1bd4f |
NM_VARIANT_TYPE_SETTING);
|
|
Packit Service |
a1bd4f |
if (!con_setting) {
|
|
Packit Service |
a1bd4f |
*out_error_message = "Failed to read connection setting";
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!g_variant_lookup(con_setting, NM_SETTING_CONNECTION_UUID, "&s", &uuid)) {
|
|
Packit Service |
a1bd4f |
*out_error_message = "Connection hash did not contain the UUID";
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!g_variant_lookup(con_setting, NM_SETTING_CONNECTION_ID, "&s", &id)) {
|
|
Packit Service |
a1bd4f |
*out_error_message = "Connection hash did not contain the ID";
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
_items_add_key0(items, NULL, "CONNECTION_UUID", uuid);
|
|
Packit Service |
a1bd4f |
_items_add_key0(items, NULL, "CONNECTION_ID", id);
|
|
Packit Service |
a1bd4f |
_items_add_key0(items, NULL, "DEVICE_IFACE", iface);
|
|
Packit Service |
a1bd4f |
_items_add_key0(items, NULL, "DEVICE_IP_IFACE", ip_iface);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Device items aren't valid if the device isn't activated */
|
|
Packit Service |
a1bd4f |
if (iface && dev_state == NM_DEVICE_STATE_ACTIVATED) {
|
|
Packit Service |
a1bd4f |
construct_proxy_items(items, device_proxy_props, NULL);
|
|
Packit Service |
a1bd4f |
construct_ip_items(items, AF_INET, device_ip4_props, NULL);
|
|
Packit Service |
a1bd4f |
construct_ip_items(items, AF_INET6, device_ip6_props, NULL);
|
|
Packit Service |
a1bd4f |
construct_device_dhcp_items(items, AF_INET, device_dhcp4_props);
|
|
Packit Service |
a1bd4f |
construct_device_dhcp_items(items, AF_INET6, device_dhcp6_props);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (vpn_ip_iface) {
|
|
Packit Service |
a1bd4f |
_items_add_key(items, NULL, "VPN_IP_IFACE", vpn_ip_iface);
|
|
Packit Service |
a1bd4f |
construct_proxy_items(items, vpn_proxy_props, "VPN_");
|
|
Packit Service |
a1bd4f |
construct_ip_items(items, AF_INET, vpn_ip4_props, "VPN_");
|
|
Packit Service |
a1bd4f |
construct_ip_items(items, AF_INET6, vpn_ip6_props, "VPN_");
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Backwards compat: 'iface' is set in this order:
|
|
Packit Service |
a1bd4f |
* 1) VPN interface name
|
|
Packit Service |
a1bd4f |
* 2) Device IP interface name
|
|
Packit Service |
a1bd4f |
* 3) Device interface anme
|
|
Packit Service |
a1bd4f |
*/
|
|
Packit Service |
a1bd4f |
if (vpn_ip_iface)
|
|
Packit Service |
a1bd4f |
*out_iface = g_strdup(vpn_ip_iface);
|
|
Packit Service |
a1bd4f |
else if (ip_iface)
|
|
Packit Service |
a1bd4f |
*out_iface = g_strdup(ip_iface);
|
|
Packit Service |
a1bd4f |
else
|
|
Packit Service |
a1bd4f |
*out_iface = g_strdup(iface);
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
done:
|
|
Packit Service |
a1bd4f |
/* The connectivity_state value will only be meaningful for 'connectivity-change' events
|
|
Packit Service |
a1bd4f |
* (otherwise it will be "UNKNOWN"), so we only set the environment variable in those cases.
|
|
Packit Service |
a1bd4f |
*/
|
|
Packit Service |
a1bd4f |
if (!NM_IN_STRSET(connectivity_state, NULL, "UNKNOWN"))
|
|
Packit Service |
a1bd4f |
_items_add_key(items, NULL, "CONNECTIVITY_STATE", connectivity_state);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
_items_add_key0(items, NULL, "PATH", g_getenv("PATH"));
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
_items_add_key(items, NULL, "NM_DISPATCHER_ACTION", action);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
*out_error_message = NULL;
|
|
Packit Service |
a1bd4f |
g_ptr_array_add(items, NULL);
|
|
Packit Service |
a1bd4f |
return (char **) g_ptr_array_free(g_steal_pointer(&items), FALSE);
|
|
Packit |
5756e2 |
}
|