summaryrefslogtreecommitdiff
path: root/libnm-core/nm-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-utils.c')
-rw-r--r--libnm-core/nm-utils.c676
1 files changed, 518 insertions, 158 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index dfa0d7cf81..37f9ca0cf4 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <stdlib.h>
#include <netinet/ether.h>
+#include <arpa/inet.h>
#include <uuid/uuid.h>
#include <gmodule.h>
@@ -32,6 +33,7 @@
#include "nm-glib-compat.h"
#include "nm-setting-private.h"
#include "crypto.h"
+#include "gsystem-local-alloc.h"
#include "nm-setting-bond.h"
#include "nm-setting-bridge.h"
@@ -662,7 +664,7 @@ _nm_utils_slist_to_strv (GSList *slist)
{
GSList *iter;
char **strv;
- int len, i = 0;
+ int len, i;
len = g_slist_length (slist);
strv = g_new (char *, len + 1);
@@ -674,6 +676,40 @@ _nm_utils_slist_to_strv (GSList *slist)
return strv;
}
+GPtrArray *
+_nm_utils_strv_to_ptrarray (char **strv)
+{
+ GPtrArray *ptrarray;
+ int i;
+
+ ptrarray = g_ptr_array_new_with_free_func (g_free);
+
+ if (strv) {
+ for (i = 0; strv[i]; i++)
+ g_ptr_array_add (ptrarray, g_strdup (strv[i]));
+ }
+
+ return ptrarray;
+}
+
+char **
+_nm_utils_ptrarray_to_strv (GPtrArray *ptrarray)
+{
+ char **strv;
+ int i;
+
+ if (!ptrarray)
+ return g_new0 (char *, 1);
+
+ strv = g_new (char *, ptrarray->len + 1);
+
+ for (i = 0; i < ptrarray->len; i++)
+ strv[i] = g_strdup (ptrarray->pdata[i]);
+ strv[i] = NULL;
+
+ return strv;
+}
+
/**
* _nm_utils_strsplit_set:
* @str: string to split
@@ -1100,16 +1136,19 @@ nm_utils_ip4_dns_from_variant (GVariant *value)
/**
* nm_utils_ip4_addresses_to_variant:
- * @addresses: (element-type NMIP4Address): an array of #NMIP4Address objects
+ * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects
+ * @gateway: (allow-none): the gateway IP address
*
- * Utility function to convert a #GPtrArray of #NMIP4Address objects into a
- * #GVariant of type 'aau' representing an array of NetworkManager IPv4
- * addresses (which are tuples of address, prefix, and gateway).
+ * Utility function to convert a #GPtrArray of #NMIPAddress objects representing
+ * IPv4 addresses into a #GVariant of type 'aau' representing an array of
+ * NetworkManager IPv4 addresses (which are tuples of address, prefix, and
+ * gateway). The "gateway" field of the first address will get the value of
+ * @gateway (if non-%NULL). In all of the other addresses, that field will be 0.
*
* Returns: (transfer none): a new floating #GVariant representing @addresses.
**/
GVariant *
-nm_utils_ip4_addresses_to_variant (GPtrArray *addresses)
+nm_utils_ip4_addresses_to_variant (GPtrArray *addresses, const char *gateway)
{
GVariantBuilder builder;
int i;
@@ -1118,12 +1157,18 @@ nm_utils_ip4_addresses_to_variant (GPtrArray *addresses)
if (addresses) {
for (i = 0; i < addresses->len; i++) {
- NMIP4Address *addr = addresses->pdata[i];
+ NMIPAddress *addr = addresses->pdata[i];
guint32 array[3];
- array[0] = nm_ip4_address_get_address (addr);
- array[1] = nm_ip4_address_get_prefix (addr);
- array[2] = nm_ip4_address_get_gateway (addr);
+ if (nm_ip_address_get_family (addr) != AF_INET)
+ continue;
+
+ nm_ip_address_get_address_binary (addr, &array[0]);
+ array[1] = nm_ip_address_get_prefix (addr);
+ if (i == 0 && gateway)
+ inet_pton (AF_INET, gateway, &array[2]);
+ else
+ array[2] = 0;
g_variant_builder_add (&builder, "@au",
g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
@@ -1137,16 +1182,19 @@ nm_utils_ip4_addresses_to_variant (GPtrArray *addresses)
/**
* nm_utils_ip4_addresses_from_variant:
* @value: a #GVariant of type 'aau'
+ * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway
*
* Utility function to convert a #GVariant of type 'aau' representing a list of
* NetworkManager IPv4 addresses (which are tuples of address, prefix, and
- * gateway) into a #GPtrArray of #NMIP4Address objects.
+ * gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field of
+ * the first address (if set) will be returned in @out_gateway; the "gateway" fields
+ * of the other addresses are ignored.
*
- * Returns: (transfer full) (element-type NMIP4Address): a newly allocated
- * #GPtrArray of #NMIP4Address objects
+ * Returns: (transfer full) (element-type NMIPAddress): a newly allocated
+ * #GPtrArray of #NMIPAddress objects
**/
GPtrArray *
-nm_utils_ip4_addresses_from_variant (GVariant *value)
+nm_utils_ip4_addresses_from_variant (GVariant *value, char **out_gateway)
{
GPtrArray *addresses;
GVariantIter iter;
@@ -1154,13 +1202,17 @@ nm_utils_ip4_addresses_from_variant (GVariant *value)
g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aau")), NULL);
+ if (out_gateway)
+ *out_gateway = NULL;
+
g_variant_iter_init (&iter, value);
- addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip4_address_unref);
+ addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
while (g_variant_iter_next (&iter, "@au", &addr_var)) {
const guint32 *addr_array;
gsize length;
- NMIP4Address *addr;
+ NMIPAddress *addr;
+ GError *error = NULL;
addr_array = g_variant_get_fixed_array (addr_var, &length, sizeof (guint32));
if (length < 3) {
@@ -1169,12 +1221,19 @@ nm_utils_ip4_addresses_from_variant (GVariant *value)
continue;
}
- addr = nm_ip4_address_new ();
- nm_ip4_address_set_address (addr, addr_array[0]);
- nm_ip4_address_set_prefix (addr, addr_array[1]);
- nm_ip4_address_set_gateway (addr, addr_array[2]);
+ addr = nm_ip_address_new_binary (AF_INET, &addr_array[0], addr_array[1], &error);
+ if (addresses->len == 0 && out_gateway) {
+ if (addr_array[2])
+ *out_gateway = g_strdup (nm_utils_inet4_ntop (addr_array[2], NULL));
+ }
+
+ if (addr)
+ g_ptr_array_add (addresses, addr);
+ else {
+ g_warning ("Ignoring invalid IP4 address: %s", error->message);
+ g_clear_error (&error);
+ }
- g_ptr_array_add (addresses, addr);
g_variant_unref (addr_var);
}
@@ -1183,11 +1242,12 @@ nm_utils_ip4_addresses_from_variant (GVariant *value)
/**
* nm_utils_ip4_routes_to_variant:
- * @routes: (element-type NMIP4Route): an array of #NMIP4Route objects
+ * @routes: (element-type NMIPRoute): an array of #NMIP4Route objects
*
- * Utility function to convert a #GPtrArray of #NMIP4Route objects into a
- * #GVariant of type 'aau' representing an array of NetworkManager IPv4 routes
- * (which are tuples of route, prefix, next hop, and metric).
+ * Utility function to convert a #GPtrArray of #NMIPRoute objects representing
+ * IPv4 routes into a #GVariant of type 'aau' representing an array of
+ * NetworkManager IPv4 routes (which are tuples of route, prefix, next hop, and
+ * metric).
*
* Returns: (transfer none): a new floating #GVariant representing @routes.
**/
@@ -1201,13 +1261,17 @@ nm_utils_ip4_routes_to_variant (GPtrArray *routes)
if (routes) {
for (i = 0; i < routes->len; i++) {
- NMIP4Route *route = routes->pdata[i];
+ NMIPRoute *route = routes->pdata[i];
guint32 array[4];
- array[0] = nm_ip4_route_get_dest (route);
- array[1] = nm_ip4_route_get_prefix (route);
- array[2] = nm_ip4_route_get_next_hop (route);
- array[3] = nm_ip4_route_get_metric (route);
+ if (nm_ip_route_get_family (route) != AF_INET)
+ continue;
+
+ nm_ip_route_get_dest_binary (route, &array[0]);
+ array[1] = nm_ip_route_get_prefix (route);
+ nm_ip_route_get_next_hop_binary (route, &array[2]);
+ /* The old routes format uses "0" for default, not "-1" */
+ array[3] = MAX (0, nm_ip_route_get_metric (route));
g_variant_builder_add (&builder, "@au",
g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
@@ -1224,10 +1288,10 @@ nm_utils_ip4_routes_to_variant (GPtrArray *routes)
*
* Utility function to convert a #GVariant of type 'aau' representing an array
* of NetworkManager IPv4 routes (which are tuples of route, prefix, next hop,
- * and metric) into a #GPtrArray of #NMIP4Route objects.
+ * and metric) into a #GPtrArray of #NMIPRoute objects.
*
- * Returns: (transfer full) (element-type NMIP4Route): a newly allocated
- * #GPtrArray of #NMIP4Route objects
+ * Returns: (transfer full) (element-type NMIPRoute): a newly allocated
+ * #GPtrArray of #NMIPRoute objects
**/
GPtrArray *
nm_utils_ip4_routes_from_variant (GVariant *value)
@@ -1239,12 +1303,13 @@ nm_utils_ip4_routes_from_variant (GVariant *value)
g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aau")), NULL);
g_variant_iter_init (&iter, value);
- routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip4_route_unref);
+ routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
while (g_variant_iter_next (&iter, "@au", &route_var)) {
const guint32 *route_array;
gsize length;
- NMIP4Route *route;
+ NMIPRoute *route;
+ GError *error = NULL;
route_array = g_variant_get_fixed_array (route_var, &length, sizeof (guint32));
if (length < 4) {
@@ -1253,13 +1318,19 @@ nm_utils_ip4_routes_from_variant (GVariant *value)
continue;
}
- route = nm_ip4_route_new ();
- nm_ip4_route_set_dest (route, route_array[0]);
- nm_ip4_route_set_prefix (route, route_array[1]);
- nm_ip4_route_set_next_hop (route, route_array[2]);
- nm_ip4_route_set_metric (route, route_array[3]);
-
- g_ptr_array_add (routes, route);
+ route = nm_ip_route_new_binary (AF_INET,
+ &route_array[0],
+ route_array[1],
+ &route_array[2],
+ /* The old routes format uses "0" for default, not "-1" */
+ route_array[3] ? (gint64) route_array[3] : -1,
+ &error);
+ if (route)
+ g_ptr_array_add (routes, route);
+ else {
+ g_warning ("Ignoring invalid IP4 route: %s", error->message);
+ g_clear_error (&error);
+ }
g_variant_unref (route_var);
}
@@ -1412,16 +1483,20 @@ nm_utils_ip6_dns_from_variant (GVariant *value)
/**
* nm_utils_ip6_addresses_to_variant:
- * @addresses: (element-type NMIP6Address): an array of #NMIP6Address objects
+ * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects
+ * @gateway: (allow-none): the gateway IP address
*
- * Utility function to convert a #GPtrArray of #NMIP6Address objects into a
- * #GVariant of type 'a(ayuay)' representing an array of NetworkManager IPv6
- * addresses (which are tuples of address, prefix, and gateway).
+ * Utility function to convert a #GPtrArray of #NMIPAddress objects representing
+ * IPv6 addresses into a #GVariant of type 'a(ayuay)' representing an array of
+ * NetworkManager IPv6 addresses (which are tuples of address, prefix, and
+ * gateway). The "gateway" field of the first address will get the value of
+ * @gateway (if non-%NULL). In all of the other addresses, that field will be
+ * all 0s.
*
* Returns: (transfer none): a new floating #GVariant representing @addresses.
**/
GVariant *
-nm_utils_ip6_addresses_to_variant (GPtrArray *addresses)
+nm_utils_ip6_addresses_to_variant (GPtrArray *addresses, const char *gateway)
{
GVariantBuilder builder;
int i;
@@ -1430,19 +1505,26 @@ nm_utils_ip6_addresses_to_variant (GPtrArray *addresses)
if (addresses) {
for (i = 0; i < addresses->len; i++) {
- NMIP6Address *addr = addresses->pdata[i];
- GVariant *ip, *gateway;
+ NMIPAddress *addr = addresses->pdata[i];
+ struct in6_addr ip_bytes, gateway_bytes;
+ GVariant *ip_var, *gateway_var;
guint32 prefix;
- ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- nm_ip6_address_get_address (addr),
- 16, 1);
- prefix = nm_ip6_address_get_prefix (addr);
- gateway = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- nm_ip6_address_get_gateway (addr),
- 16, 1);
+ if (nm_ip_address_get_family (addr) != AF_INET6)
+ continue;
+
+ nm_ip_address_get_address_binary (addr, &ip_bytes);
+ ip_var = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &ip_bytes, 16, 1);
- g_variant_builder_add (&builder, "(@ayu@ay)", ip, prefix, gateway);
+ prefix = nm_ip_address_get_prefix (addr);
+
+ if (i == 0 && gateway)
+ inet_pton (AF_INET6, gateway, &gateway_bytes);
+ else
+ memset (&gateway_bytes, 0, sizeof (gateway_bytes));
+ gateway_var = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &gateway_bytes, 16, 1);
+
+ g_variant_builder_add (&builder, "(@ayu@ay)", ip_var, prefix, gateway_var);
}
}
@@ -1452,16 +1534,19 @@ nm_utils_ip6_addresses_to_variant (GPtrArray *addresses)
/**
* nm_utils_ip6_addresses_from_variant:
* @value: a #GVariant of type 'a(ayuay)'
+ * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway
*
* Utility function to convert a #GVariant of type 'a(ayuay)' representing a
* list of NetworkManager IPv6 addresses (which are tuples of address, prefix,
- * and gateway) into a #GPtrArray of #NMIP6Address objects.
+ * and gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field
+ * of the first address (if set) will be returned in @out_gateway; the "gateway"
+ * fields of the other addresses are ignored.
*
- * Returns: (transfer full) (element-type NMIP6Address): a newly allocated
- * #GPtrArray of #NMIP6Address objects
+ * Returns: (transfer full) (element-type NMIPAddress): a newly allocated
+ * #GPtrArray of #NMIPAddress objects
**/
GPtrArray *
-nm_utils_ip6_addresses_from_variant (GVariant *value)
+nm_utils_ip6_addresses_from_variant (GVariant *value, char **out_gateway)
{
GVariantIter iter;
GVariant *addr_var, *gateway_var;
@@ -1470,13 +1555,17 @@ nm_utils_ip6_addresses_from_variant (GVariant *value)
g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(ayuay)")), NULL);
+ if (out_gateway)
+ *out_gateway = NULL;
+
g_variant_iter_init (&iter, value);
- addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip6_address_unref);
+ addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
while (g_variant_iter_next (&iter, "(@ayu@ay)", &addr_var, &prefix, &gateway_var)) {
- NMIP6Address *addr;
+ NMIPAddress *addr;
const struct in6_addr *addr_bytes, *gateway_bytes;
gsize addr_len, gateway_len;
+ GError *error = NULL;
if ( !g_variant_is_of_type (addr_var, G_VARIANT_TYPE_BYTESTRING)
|| !g_variant_is_of_type (gateway_var, G_VARIANT_TYPE_BYTESTRING)) {
@@ -1490,23 +1579,25 @@ nm_utils_ip6_addresses_from_variant (GVariant *value)
__func__, (int) addr_len);
goto next;
}
- if (prefix > 128) {
- g_warning ("%s: ignoring invalid IP6 prefix %d",
- __func__, prefix);
- goto next;
- }
- gateway_bytes = g_variant_get_fixed_array (gateway_var, &gateway_len, 1);
- if (gateway_len != 16) {
- g_warning ("%s: ignoring invalid IP6 address of length %d",
- __func__, (int) gateway_len);
- goto next;
+
+ if (addresses->len == 0 && out_gateway) {
+ gateway_bytes = g_variant_get_fixed_array (gateway_var, &gateway_len, 1);
+ if (gateway_len != 16) {
+ g_warning ("%s: ignoring invalid IP6 address of length %d",
+ __func__, (int) gateway_len);
+ goto next;
+ }
+ if (!IN6_IS_ADDR_UNSPECIFIED (gateway_bytes))
+ *out_gateway = g_strdup (nm_utils_inet6_ntop (gateway_bytes, NULL));
}
- addr = nm_ip6_address_new ();
- nm_ip6_address_set_address (addr, addr_bytes);
- nm_ip6_address_set_prefix (addr, prefix);
- nm_ip6_address_set_gateway (addr, gateway_bytes);
- g_ptr_array_add (addresses, addr);
+ addr = nm_ip_address_new_binary (AF_INET6, addr_bytes, prefix, &error);
+ if (addr)
+ g_ptr_array_add (addresses, addr);
+ else {
+ g_warning ("Ignoring invalid IP4 address: %s", error->message);
+ g_clear_error (&error);
+ }
next:
g_variant_unref (addr_var);
@@ -1518,11 +1609,12 @@ nm_utils_ip6_addresses_from_variant (GVariant *value)
/**
* nm_utils_ip6_routes_to_variant:
- * @routes: (element-type NMIP6Route): an array of #NMIP6Route objects
+ * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects
*
- * Utility function to convert a #GPtrArray of #NMIP6Route objects into a
- * #GVariant of type 'a(ayuayu)' representing an array of NetworkManager IPv6
- * routes (which are tuples of route, prefix, next hop, and metric).
+ * Utility function to convert a #GPtrArray of #NMIPRoute objects representing
+ * IPv6 routes into a #GVariant of type 'a(ayuayu)' representing an array of
+ * NetworkManager IPv6 routes (which are tuples of route, prefix, next hop, and
+ * metric).
*
* Returns: (transfer none): a new floating #GVariant representing @routes.
**/
@@ -1536,18 +1628,21 @@ nm_utils_ip6_routes_to_variant (GPtrArray *routes)
if (routes) {
for (i = 0; i < routes->len; i++) {
- NMIP6Route *route = routes->pdata[i];
+ NMIPRoute *route = routes->pdata[i];
+ struct in6_addr dest_bytes, next_hop_bytes;
GVariant *dest, *next_hop;
guint32 prefix, metric;
- dest = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- nm_ip6_route_get_dest (route),
- 16, 1);
- prefix = nm_ip6_route_get_prefix (route);
- next_hop = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- nm_ip6_route_get_next_hop (route),
- 16, 1);
- metric = nm_ip6_route_get_metric (route);
+ if (nm_ip_route_get_family (route) != AF_INET6)
+ continue;
+
+ nm_ip_route_get_dest_binary (route, &dest_bytes);
+ dest = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &dest_bytes, 16, 1);
+ prefix = nm_ip_route_get_prefix (route);
+ nm_ip_route_get_next_hop_binary (route, &next_hop_bytes);
+ next_hop = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &next_hop_bytes, 16, 1);
+ /* The old routes format uses "0" for default, not "-1" */
+ metric = MAX (0, nm_ip_route_get_metric (route));
g_variant_builder_add (&builder, "(@ayu@ayu)", dest, prefix, next_hop, metric);
}
@@ -1562,10 +1657,10 @@ nm_utils_ip6_routes_to_variant (GPtrArray *routes)
*
* Utility function to convert a #GVariant of type 'a(ayuayu)' representing an
* array of NetworkManager IPv6 routes (which are tuples of route, prefix, next
- * hop, and metric) into a #GPtrArray of #NMIP6Route objects.
+ * hop, and metric) into a #GPtrArray of #NMIPRoute objects.
*
- * Returns: (transfer full) (element-type NMIP6Route): a newly allocated
- * #GPtrArray of #NMIP6Route objects
+ * Returns: (transfer full) (element-type NMIPRoute): a newly allocated
+ * #GPtrArray of #NMIPRoute objects
**/
GPtrArray *
nm_utils_ip6_routes_from_variant (GVariant *value)
@@ -1579,11 +1674,12 @@ nm_utils_ip6_routes_from_variant (GVariant *value)
g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(ayuayu)")), NULL);
- routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip6_route_unref);
+ routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
g_variant_iter_init (&iter, value);
while (g_variant_iter_next (&iter, "(@ayu@ayu)", &dest_var, &prefix, &next_hop_var, &metric)) {
- NMIP6Route *route;
+ NMIPRoute *route;
+ GError *error = NULL;
if ( !g_variant_is_of_type (dest_var, G_VARIANT_TYPE_BYTESTRING)
|| !g_variant_is_of_type (next_hop_var, G_VARIANT_TYPE_BYTESTRING)) {
@@ -1597,6 +1693,7 @@ nm_utils_ip6_routes_from_variant (GVariant *value)
__func__, (int) dest_len);
goto next;
}
+
next_hop = g_variant_get_fixed_array (next_hop_var, &next_hop_len, 1);
if (next_hop_len != 16) {
g_warning ("%s: ignoring invalid IP6 address of length %d",
@@ -1604,12 +1701,15 @@ nm_utils_ip6_routes_from_variant (GVariant *value)
goto next;
}
- route = nm_ip6_route_new ();
- nm_ip6_route_set_dest (route, dest);
- nm_ip6_route_set_prefix (route, prefix);
- nm_ip6_route_set_next_hop (route, next_hop);
- nm_ip6_route_set_metric (route, metric);
- g_ptr_array_add (routes, route);
+ route = nm_ip_route_new_binary (AF_INET6, dest, prefix, next_hop,
+ metric ? (gint64) metric : -1,
+ &error);
+ if (route)
+ g_ptr_array_add (routes, route);
+ else {
+ g_warning ("Ignoring invalid IP6 route: %s", error->message);
+ g_clear_error (&error);
+ }
next:
g_variant_unref (dest_var);
@@ -1620,6 +1720,248 @@ nm_utils_ip6_routes_from_variant (GVariant *value)
}
/**
+ * nm_utils_ip_addresses_to_variant:
+ * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects
+ *
+ * Utility function to convert a #GPtrArray of #NMIPAddress objects representing
+ * IPv4 or IPv6 addresses into a #GVariant of type 'aa{sv}' representing an
+ * array of new-style NetworkManager IP addresses. All addresses will include
+ * "address" (an IP address string), and "prefix" (a uint). Some addresses may
+ * include additional attributes.
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @addresses.
+ **/
+GVariant *
+nm_utils_ip_addresses_to_variant (GPtrArray *addresses)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ if (addresses) {
+ for (i = 0; i < addresses->len; i++) {
+ NMIPAddress *addr = addresses->pdata[i];
+ GVariantBuilder addr_builder;
+ char **names;
+ int n;
+
+ g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "address",
+ g_variant_new_string (nm_ip_address_get_address (addr)));
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "prefix",
+ g_variant_new_uint32 (nm_ip_address_get_prefix (addr)));
+
+ names = nm_ip_address_get_attribute_names (addr);
+ for (n = 0; names[n]; n++) {
+ g_variant_builder_add (&addr_builder, "{sv}",
+ names[n],
+ nm_ip_address_get_attribute (addr, names[n]));
+ }
+ g_strfreev (names);
+
+ g_variant_builder_add (&builder, "a{sv}", &addr_builder);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip_addresses_from_variant:
+ * @value: a #GVariant of type 'aa{sv}'
+ * @family: an IP address family
+ *
+ * Utility function to convert a #GVariant representing a list of new-style
+ * NetworkManager IPv4 or IPv6 addresses (as described in the documentation for
+ * nm_utils_ip_addresses_to_variant()) into a #GPtrArray of #NMIPAddress
+ * objects.
+ *
+ * Returns: (transfer full) (element-type NMIPAddress): a newly allocated
+ * #GPtrArray of #NMIPAddress objects
+ **/
+GPtrArray *
+nm_utils_ip_addresses_from_variant (GVariant *value,
+ int family)
+{
+ GPtrArray *addresses;
+ GVariantIter iter, attrs_iter;
+ GVariant *addr_var;
+ const char *ip;
+ guint32 prefix;
+ const char *attr_name;
+ GVariant *attr_val;
+ NMIPAddress *addr;
+ GError *error = NULL;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), NULL);
+
+ g_variant_iter_init (&iter, value);
+ addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
+
+ while (g_variant_iter_next (&iter, "@a{sv}", &addr_var)) {
+ if ( !g_variant_lookup (addr_var, "address", "&s", &ip)
+ || !g_variant_lookup (addr_var, "prefix", "u", &prefix)) {
+ g_warning ("Ignoring invalid address");
+ g_variant_unref (addr_var);
+ continue;
+ }
+
+ addr = nm_ip_address_new (family, ip, prefix, &error);
+ if (!addr) {
+ g_warning ("Ignoring invalid address: %s", error->message);
+ g_clear_error (&error);
+ g_variant_unref (addr_var);
+ continue;
+ }
+
+ g_variant_iter_init (&attrs_iter, addr_var);
+ while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_val)) {
+ if ( strcmp (attr_name, "address") != 0
+ && strcmp (attr_name, "prefix") != 0)
+ nm_ip_address_set_attribute (addr, attr_name, attr_val);
+ g_variant_unref (attr_val);
+ }
+
+ g_ptr_array_add (addresses, addr);
+ }
+
+ return addresses;
+}
+
+/**
+ * nm_utils_ip_routes_to_variant:
+ * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects
+ *
+ * Utility function to convert a #GPtrArray of #NMIPRoute objects representing
+ * IPv4 or IPv6 routes into a #GVariant of type 'aa{sv}' representing an array
+ * of new-style NetworkManager IP routes (which are tuples of destination,
+ * prefix, next hop, metric, and additional attributes).
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @routes.
+ **/
+GVariant *
+nm_utils_ip_routes_to_variant (GPtrArray *routes)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ if (routes) {
+ for (i = 0; i < routes->len; i++) {
+ NMIPRoute *route = routes->pdata[i];
+ GVariantBuilder route_builder;
+ char **names;
+ int n;
+
+ g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&route_builder, "{sv}",
+ "dest",
+ g_variant_new_string (nm_ip_route_get_dest (route)));
+ g_variant_builder_add (&route_builder, "{sv}",
+ "prefix",
+ g_variant_new_uint32 (nm_ip_route_get_prefix (route)));
+ if (nm_ip_route_get_next_hop (route)) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ "next-hop",
+ g_variant_new_string (nm_ip_route_get_next_hop (route)));
+ }
+ if (nm_ip_route_get_metric (route) != -1) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ "metric",
+ g_variant_new_uint32 ((guint32) nm_ip_route_get_metric (route)));
+ }
+
+ names = nm_ip_route_get_attribute_names (route);
+ for (n = 0; names[n]; n++) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ names[n],
+ nm_ip_route_get_attribute (route, names[n]));
+ }
+ g_strfreev (names);
+
+ g_variant_builder_add (&builder, "a{sv}", &route_builder);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip_routes_from_variant:
+ * @value: a #GVariant of type 'aa{sv}'
+ * @family: an IP address family
+ *
+ * Utility function to convert a #GVariant representing a list of new-style
+ * NetworkManager IPv4 or IPv6 addresses (which are tuples of destination,
+ * prefix, next hop, metric, and additional attributes) into a #GPtrArray of
+ * #NMIPRoute objects.
+ *
+ * Returns: (transfer full) (element-type NMIPRoute): a newly allocated
+ * #GPtrArray of #NMIPRoute objects
+ **/
+GPtrArray *
+nm_utils_ip_routes_from_variant (GVariant *value,
+ int family)
+{
+ GPtrArray *routes;
+ GVariantIter iter, attrs_iter;
+ GVariant *route_var;
+ const char *dest, *next_hop;
+ guint32 prefix, metric32;
+ gint64 metric;
+ const char *attr_name;
+ GVariant *attr_val;
+ NMIPRoute *route;
+ GError *error = NULL;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), NULL);
+
+ g_variant_iter_init (&iter, value);
+ routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
+
+ while (g_variant_iter_next (&iter, "@a{sv}", &route_var)) {
+ if ( !g_variant_lookup (route_var, "dest", "&s", &dest)
+ || !g_variant_lookup (route_var, "prefix", "u", &prefix)) {
+ g_warning ("Ignoring invalid address");
+ g_variant_unref (route_var);
+ continue;
+ }
+ if (!g_variant_lookup (route_var, "next-hop", "&s", &next_hop))
+ next_hop = NULL;
+ if (g_variant_lookup (route_var, "metric", "u", &metric32))
+ metric = metric32;
+ else
+ metric = -1;
+
+ route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &error);
+ if (!route) {
+ g_warning ("Ignoring invalid route: %s", error->message);
+ g_clear_error (&error);
+ g_variant_unref (route_var);
+ continue;
+ }
+
+ g_variant_iter_init (&attrs_iter, route_var);
+ while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_val)) {
+ if ( strcmp (attr_name, "dest") != 0
+ && strcmp (attr_name, "prefix") != 0
+ && strcmp (attr_name, "next-hop") != 0
+ && strcmp (attr_name, "metric") != 0)
+ nm_ip_route_set_attribute (route, attr_name, attr_val);
+ g_variant_unref (attr_val);
+ }
+
+ g_ptr_array_add (routes, route);
+ }
+
+ return routes;
+}
+
+/**
* nm_utils_uuid_generate:
*
* Returns: a newly allocated UUID suitable for use as the #NMSettingConnection
@@ -1759,7 +2101,7 @@ nm_utils_rsa_key_encrypt_helper (const char *cipher,
if (!in_password) {
if (!crypto_randomize (pw_buf, sizeof (pw_buf), error))
return NULL;
- in_password = tmp_password = nm_utils_bin2hexstr ((const char *) pw_buf, sizeof (pw_buf), -1);
+ in_password = tmp_password = nm_utils_bin2hexstr (pw_buf, sizeof (pw_buf), -1);
}
if (g_strcmp0 (cipher, CIPHER_AES_CBC) == 0)
@@ -1783,7 +2125,7 @@ nm_utils_rsa_key_encrypt_helper (const char *cipher,
g_string_append (pem, "Proc-Type: 4,ENCRYPTED\n");
/* Convert the salt to a hex string */
- tmp = nm_utils_bin2hexstr ((const char *) salt, salt_len, salt_len * 2);
+ tmp = nm_utils_bin2hexstr (salt, salt_len, salt_len * 2);
g_string_append_printf (pem, "DEK-Info: %s,%s\n\n", cipher, tmp);
g_free (tmp);
@@ -1892,9 +2234,9 @@ nm_utils_rsa_key_encrypt_aes (const guint8 *data,
* nm_utils_file_is_pkcs12:
* @filename: name of the file to test
*
- * Utility function to find out if the @filename is in PKCS#12 format.
+ * Utility function to find out if the @filename is in PKCS#<!-- -->12 format.
*
- * Returns: %TRUE if the file is PKCS#12, %FALSE if it is not
+ * Returns: %TRUE if the file is PKCS#<!-- -->12, %FALSE if it is not
**/
gboolean
nm_utils_file_is_pkcs12 (const char *filename)
@@ -2535,13 +2877,13 @@ _nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
/**
* nm_utils_bin2hexstr:
- * @bytes: an array of bytes
+ * @src: an array of bytes
* @len: the length of the @bytes array
* @final_len: an index where to cut off the returned string, or -1
*
- * Converts a byte-array @bytes into a hexadecimal string.
- * If @final_len is greater than -1, the returned string is terminated at
- * that index (returned_string[final_len] == '\0'),
+ * Converts the byte array @src into a hexadecimal string. If @final_len is
+ * greater than -1, the returned string is terminated at that index
+ * (returned_string[final_len] == '\0'),
*
* Return value: (transfer full): the textual form of @bytes
*/
@@ -2550,9 +2892,10 @@ _nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
* copyright Red Hat, Inc. under terms of the LGPL.
*/
char *
-nm_utils_bin2hexstr (const char *bytes, int len, int final_len)
+nm_utils_bin2hexstr (gconstpointer src, gsize len, int final_len)
{
static char hex_digits[] = "0123456789abcdef";
+ const guint8 *bytes = src;
char *result;
int i;
gsize buflen = (len * 2) + 1;
@@ -2577,64 +2920,61 @@ nm_utils_bin2hexstr (const char *bytes, int len, int final_len)
return result;
}
-/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
/**
- * nm_utils_hex2byte:
- * @hex: a string representing a hex byte
+ * nm_utils_hexstr2bin:
+ * @hex: a string of hexadecimal characters with optional ':' separators
*
- * Converts a hex string (2 characters) into its byte representation.
+ * Converts a hexadecimal string @hex into an array of bytes. The optional
+ * separator ':' may be used between single or pairs of hexadecimal characters,
+ * eg "00:11" or "0:1". Any "0x" at the beginning of @hex is ignored. @hex
+ * may not start or end with ':'.
*
- * Return value: a byte, or -1 if @hex doesn't represent a hex byte
+ * Return value: (transfer full): the converted bytes, or %NULL on error
*/
-int
-nm_utils_hex2byte (const char *hex)
+GBytes *
+nm_utils_hexstr2bin (const char *hex)
{
+ guint i = 0, x = 0;
+ gs_free guint8 *c = NULL;
int a, b;
- a = g_ascii_xdigit_value (*hex++);
- if (a < 0)
- return -1;
- b = g_ascii_xdigit_value (*hex++);
- if (b < 0)
- return -1;
- return (a << 4) | b;
-}
+ gboolean found_colon = FALSE;
-/**
- * nm_utils_hexstr2bin:
- * @hex: an hex string
- * @len: the length of the @hex string (it has to be even)
- *
- * Converts a hexadecimal string @hex into a byte-array. The returned array
- * length is @len/2.
- *
- * Return value: (transfer full): a array of bytes, or %NULL on error
- */
-char *
-nm_utils_hexstr2bin (const char *hex, size_t len)
-{
- size_t i;
- int a;
- const char * ipos = hex;
- char * buf = NULL;
- char * opos;
+ g_return_val_if_fail (hex != NULL, NULL);
- /* Length must be a multiple of 2 */
- if ((len % 2) != 0)
- return NULL;
+ if (strncasecmp (hex, "0x", 2) == 0)
+ hex += 2;
+ found_colon = !!strchr (hex, ':');
+
+ c = g_malloc (strlen (hex) / 2 + 1);
+ for (;;) {
+ a = g_ascii_xdigit_value (hex[i++]);
+ if (a < 0)
+ return NULL;
- opos = buf = g_malloc0 ((len / 2) + 1);
- for (i = 0; i < len; i += 2) {
- a = nm_utils_hex2byte (ipos);
- if (a < 0) {
- g_free (buf);
+ if (hex[i] && hex[i] != ':') {
+ b = g_ascii_xdigit_value (hex[i++]);
+ if (b < 0)
+ return NULL;
+ c[x++] = ((guint) a << 4) | ((guint) b);
+ } else
+ c[x++] = (guint) a;
+
+ if (!hex[i])
+ break;
+ if (hex[i] == ':') {
+ if (!hex[i + 1]) {
+ /* trailing ':' is invalid */
+ return NULL;
+ }
+ i++;
+ } else if (found_colon) {
+ /* If colons exist, they must delimit 1 or 2 hex chars */
return NULL;
}
- *opos++ = a;
- ipos += 2;
}
- return buf;
+
+ return g_bytes_new (c, x);
}
-/* End from hostap */
/**
* nm_utils_iface_valid_name:
@@ -2751,6 +3091,28 @@ nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst)
}
/**
+ * nm_utils_ipaddr_valid:
+ * @family: %AF_INET or %AF_INET6, or %AF_UNSPEC to accept either
+ * @ip: an IP address
+ *
+ * Checks if @ip contains a valid IP address of the given family.
+ *
+ * Return value: %TRUE or %FALSE
+ */
+gboolean
+nm_utils_ipaddr_valid (int family, const char *ip)
+{
+ guint8 buf[sizeof (struct in6_addr)];
+
+ g_return_val_if_fail (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC, FALSE);
+
+ if (family == AF_UNSPEC)
+ family = strchr (ip, ':') ? AF_INET6 : AF_INET;
+
+ return inet_pton (family, ip, buf) == 1;
+}
+
+/**
* nm_utils_check_virtual_device_compatibility:
* @virtual_type: a virtual connection type
* @other_type: a connection type to test against @virtual_type
@@ -2809,5 +3171,3 @@ nm_utils_check_virtual_device_compatibility (GType virtual_type, GType other_typ
return FALSE;
}
}
-
-