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