2008-07-27 20:03:46 +00:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
2007-11-07 16:06:43 +00:00
|
|
|
|
2007-09-12 16:23:53 +00:00
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* Ray Strode <rstrode@redhat.com>
|
2008-07-27 20:03:46 +00:00
|
|
|
* Dan Williams <dcbw@redhat.com>
|
|
|
|
|
* Tambet Ingo <tambet@gmail.com>
|
2007-09-12 16:23:53 +00:00
|
|
|
*
|
2008-07-27 20:03:46 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
2007-09-12 16:23:53 +00:00
|
|
|
*
|
2008-07-27 20:03:46 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2007-09-12 16:23:53 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2008-07-27 20:03:46 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
2007-09-12 16:23:53 +00:00
|
|
|
*
|
2008-07-27 20:03:46 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
|
* Boston, MA 02110-1301 USA.
|
2007-09-12 16:23:53 +00:00
|
|
|
*
|
2012-07-16 14:42:06 +02:00
|
|
|
* (C) Copyright 2005 - 2012 Red Hat, Inc.
|
2007-09-12 16:23:53 +00:00
|
|
|
*/
|
|
|
|
|
|
2011-03-14 01:00:56 -05:00
|
|
|
#include "config.h"
|
2007-09-12 16:23:53 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <errno.h>
|
2007-11-26 16:59:47 +00:00
|
|
|
#include <arpa/inet.h>
|
2011-10-10 16:00:28 -04:00
|
|
|
#include <netinet/ether.h>
|
|
|
|
|
#include <linux/if_infiniband.h>
|
2007-09-12 16:23:53 +00:00
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <glib-object.h>
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 16:01:50 -07:00
|
|
|
#include <glib/gi18n.h>
|
2007-11-07 16:06:43 +00:00
|
|
|
#include <dbus/dbus-glib.h>
|
2008-08-27 02:57:21 +00:00
|
|
|
#include <uuid/uuid.h>
|
|
|
|
|
|
2007-09-12 16:23:53 +00:00
|
|
|
#include "nm-utils.h"
|
2008-11-20 20:17:01 +00:00
|
|
|
#include "nm-utils-private.h"
|
2007-10-17 21:40:17 +00:00
|
|
|
#include "NetworkManager.h"
|
2008-03-29 21:35:41 +00:00
|
|
|
#include "nm-dbus-glib-types.h"
|
2008-05-06 21:41:08 +00:00
|
|
|
#include "nm-setting-ip4-config.h"
|
2008-06-26 21:30:33 +00:00
|
|
|
#include "nm-setting-ip6-config.h"
|
2008-08-27 02:57:21 +00:00
|
|
|
#include "crypto.h"
|
2007-09-12 16:23:53 +00:00
|
|
|
|
2008-11-24 16:55:37 +00:00
|
|
|
/**
|
|
|
|
|
* SECTION:nm-utils
|
|
|
|
|
* @short_description: Utility functions
|
|
|
|
|
* @include: nm-utils.h
|
|
|
|
|
*
|
|
|
|
|
* A collection of utility functions for working SSIDs, IP addresses, WiFi
|
|
|
|
|
* access points and devices, among other things.
|
|
|
|
|
*/
|
|
|
|
|
|
2007-10-09 10:04:07 +00:00
|
|
|
struct EncodingTriplet
|
|
|
|
|
{
|
|
|
|
|
const char *encoding1;
|
|
|
|
|
const char *encoding2;
|
|
|
|
|
const char *encoding3;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct IsoLangToEncodings
|
|
|
|
|
{
|
|
|
|
|
const char * lang;
|
|
|
|
|
struct EncodingTriplet encodings;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* 5-letter language codes */
|
|
|
|
|
static const struct IsoLangToEncodings isoLangEntries5[] =
|
|
|
|
|
{
|
|
|
|
|
/* Simplified Chinese */
|
|
|
|
|
{ "zh_cn", {"euc-cn", "gb2312", "gb18030"} }, /* PRC */
|
|
|
|
|
{ "zh_sg", {"euc-cn", "gb2312", "gb18030"} }, /* Singapore */
|
|
|
|
|
|
|
|
|
|
/* Traditional Chinese */
|
|
|
|
|
{ "zh_tw", {"big5", "euc-tw", NULL} }, /* Taiwan */
|
|
|
|
|
{ "zh_hk", {"big5", "euc-tw", "big5-hkcs"} },/* Hong Kong */
|
|
|
|
|
{ "zh_mo", {"big5", "euc-tw", NULL} }, /* Macau */
|
|
|
|
|
|
|
|
|
|
/* Table end */
|
|
|
|
|
{ NULL, {NULL, NULL, NULL} }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* 2-letter language codes; we don't care about the other 3 in this table */
|
|
|
|
|
static const struct IsoLangToEncodings isoLangEntries2[] =
|
|
|
|
|
{
|
|
|
|
|
/* Japanese */
|
|
|
|
|
{ "ja", {"euc-jp", "shift_jis", "iso-2022-jp"} },
|
|
|
|
|
|
|
|
|
|
/* Korean */
|
|
|
|
|
{ "ko", {"euc-kr", "iso-2022-kr", "johab"} },
|
|
|
|
|
|
|
|
|
|
/* Thai */
|
|
|
|
|
{ "th", {"iso-8859-11","windows-874", NULL} },
|
|
|
|
|
|
|
|
|
|
/* Central European */
|
|
|
|
|
{ "hu", {"iso-8859-2", "windows-1250", NULL} }, /* Hungarian */
|
|
|
|
|
{ "cs", {"iso-8859-2", "windows-1250", NULL} }, /* Czech */
|
|
|
|
|
{ "hr", {"iso-8859-2", "windows-1250", NULL} }, /* Croatian */
|
|
|
|
|
{ "pl", {"iso-8859-2", "windows-1250", NULL} }, /* Polish */
|
|
|
|
|
{ "ro", {"iso-8859-2", "windows-1250", NULL} }, /* Romanian */
|
|
|
|
|
{ "sk", {"iso-8859-2", "windows-1250", NULL} }, /* Slovakian */
|
|
|
|
|
{ "sl", {"iso-8859-2", "windows-1250", NULL} }, /* Slovenian */
|
|
|
|
|
{ "sh", {"iso-8859-2", "windows-1250", NULL} }, /* Serbo-Croatian */
|
|
|
|
|
|
|
|
|
|
/* Cyrillic */
|
|
|
|
|
{ "ru", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Russian */
|
|
|
|
|
{ "be", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Belorussian */
|
|
|
|
|
{ "bg", {"windows-1251","koi8-r", "iso-8859-5"} }, /* Bulgarian */
|
|
|
|
|
{ "mk", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Macedonian */
|
|
|
|
|
{ "sr", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Serbian */
|
|
|
|
|
{ "uk", {"koi8-u", "koi8-r", "windows-1251"} }, /* Ukranian */
|
|
|
|
|
|
|
|
|
|
/* Arabic */
|
|
|
|
|
{ "ar", {"iso-8859-6", "windows-1256", NULL} },
|
|
|
|
|
|
2010-05-31 15:32:13 +02:00
|
|
|
/* Baltic */
|
2007-10-09 10:04:07 +00:00
|
|
|
{ "et", {"iso-8859-4", "windows-1257", NULL} }, /* Estonian */
|
|
|
|
|
{ "lt", {"iso-8859-4", "windows-1257", NULL} }, /* Lithuanian */
|
|
|
|
|
{ "lv", {"iso-8859-4", "windows-1257", NULL} }, /* Latvian */
|
|
|
|
|
|
|
|
|
|
/* Greek */
|
|
|
|
|
{ "el", {"iso-8859-7", "windows-1253", NULL} },
|
|
|
|
|
|
|
|
|
|
/* Hebrew */
|
|
|
|
|
{ "he", {"iso-8859-8", "windows-1255", NULL} },
|
|
|
|
|
{ "iw", {"iso-8859-8", "windows-1255", NULL} },
|
|
|
|
|
|
|
|
|
|
/* Turkish */
|
|
|
|
|
{ "tr", {"iso-8859-9", "windows-1254", NULL} },
|
|
|
|
|
|
|
|
|
|
/* Table end */
|
|
|
|
|
{ NULL, {NULL, NULL, NULL} }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static GHashTable * langToEncodings5 = NULL;
|
|
|
|
|
static GHashTable * langToEncodings2 = NULL;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
init_lang_to_encodings_hash (void)
|
|
|
|
|
{
|
2008-04-08 21:15:45 +00:00
|
|
|
struct IsoLangToEncodings *enc;
|
2007-10-09 10:04:07 +00:00
|
|
|
|
2008-04-08 21:15:45 +00:00
|
|
|
if (G_UNLIKELY (langToEncodings5 == NULL)) {
|
2007-10-09 10:04:07 +00:00
|
|
|
/* Five-letter codes */
|
2008-04-08 21:15:45 +00:00
|
|
|
enc = (struct IsoLangToEncodings *) &isoLangEntries5[0];
|
2007-10-09 10:04:07 +00:00
|
|
|
langToEncodings5 = g_hash_table_new (g_str_hash, g_str_equal);
|
2008-04-08 21:15:45 +00:00
|
|
|
while (enc->lang) {
|
2007-10-09 10:04:07 +00:00
|
|
|
g_hash_table_insert (langToEncodings5, (gpointer) enc->lang,
|
|
|
|
|
(gpointer) &enc->encodings);
|
|
|
|
|
enc++;
|
|
|
|
|
}
|
2008-04-08 21:15:45 +00:00
|
|
|
}
|
2007-10-09 10:04:07 +00:00
|
|
|
|
2008-04-08 21:15:45 +00:00
|
|
|
if (G_UNLIKELY (langToEncodings2 == NULL)) {
|
2007-10-09 10:04:07 +00:00
|
|
|
/* Two-letter codes */
|
2008-04-08 21:15:45 +00:00
|
|
|
enc = (struct IsoLangToEncodings *) &isoLangEntries2[0];
|
2007-10-09 10:04:07 +00:00
|
|
|
langToEncodings2 = g_hash_table_new (g_str_hash, g_str_equal);
|
2008-04-08 21:15:45 +00:00
|
|
|
while (enc->lang) {
|
2007-10-09 10:04:07 +00:00
|
|
|
g_hash_table_insert (langToEncodings2, (gpointer) enc->lang,
|
|
|
|
|
(gpointer) &enc->encodings);
|
|
|
|
|
enc++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
get_encodings_for_lang (const char *lang,
|
|
|
|
|
char **encoding1,
|
|
|
|
|
char **encoding2,
|
|
|
|
|
char **encoding3)
|
|
|
|
|
{
|
|
|
|
|
struct EncodingTriplet * encodings;
|
|
|
|
|
gboolean success = FALSE;
|
|
|
|
|
char * tmp_lang;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (lang != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (encoding1 != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (encoding2 != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (encoding3 != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
*encoding1 = "iso-8859-1";
|
|
|
|
|
*encoding2 = "windows-1251";
|
|
|
|
|
*encoding3 = NULL;
|
|
|
|
|
|
|
|
|
|
init_lang_to_encodings_hash ();
|
|
|
|
|
|
|
|
|
|
tmp_lang = g_strdup (lang);
|
|
|
|
|
if ((encodings = g_hash_table_lookup (langToEncodings5, tmp_lang)))
|
|
|
|
|
{
|
|
|
|
|
*encoding1 = (char *) encodings->encoding1;
|
|
|
|
|
*encoding2 = (char *) encodings->encoding2;
|
|
|
|
|
*encoding3 = (char *) encodings->encoding3;
|
|
|
|
|
success = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Truncate tmp_lang to length of 2 */
|
|
|
|
|
if (strlen (tmp_lang) > 2)
|
|
|
|
|
tmp_lang[2] = '\0';
|
|
|
|
|
if (!success && (encodings = g_hash_table_lookup (langToEncodings2, tmp_lang)))
|
|
|
|
|
{
|
|
|
|
|
*encoding1 = (char *) encodings->encoding1;
|
|
|
|
|
*encoding2 = (char *) encodings->encoding2;
|
|
|
|
|
*encoding3 = (char *) encodings->encoding3;
|
|
|
|
|
success = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (tmp_lang);
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-08 18:35:21 +00:00
|
|
|
/* init, deinit for libnm_util */
|
|
|
|
|
|
|
|
|
|
static gboolean initialized = FALSE;
|
|
|
|
|
|
2008-11-20 20:17:01 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_init:
|
|
|
|
|
* @error: location to store error, or %NULL
|
|
|
|
|
*
|
|
|
|
|
* Initializes libnm-util; should be called when starting and program that
|
|
|
|
|
* uses libnm-util. Sets up an atexit() handler to ensure de-initialization
|
|
|
|
|
* is performed, but calling nm_utils_deinit() to explicitly deinitialize
|
|
|
|
|
* libnm-util can also be done. This function can be called more than once.
|
|
|
|
|
*
|
|
|
|
|
* Returns: TRUE if the initialization was successful, FALSE on failure.
|
|
|
|
|
**/
|
2008-09-08 18:35:21 +00:00
|
|
|
gboolean
|
|
|
|
|
nm_utils_init (GError **error)
|
|
|
|
|
{
|
|
|
|
|
if (!initialized) {
|
2011-03-31 13:29:19 -05:00
|
|
|
initialized = TRUE;
|
|
|
|
|
|
2008-11-20 20:17:01 +00:00
|
|
|
if (!crypto_init (error))
|
2008-09-08 18:35:21 +00:00
|
|
|
return FALSE;
|
2008-11-20 20:17:01 +00:00
|
|
|
|
2010-04-19 10:14:44 -07:00
|
|
|
_nm_utils_register_value_transformations ();
|
2008-09-08 18:35:21 +00:00
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 20:17:01 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_deinit:
|
|
|
|
|
*
|
|
|
|
|
* Frees all resources used internally by libnm-util. This function is called
|
|
|
|
|
* from an atexit() handler, set up by nm_utils_init(), but is safe to be called
|
|
|
|
|
* more than once. Subsequent calls have no effect until nm_utils_init() is
|
|
|
|
|
* called again.
|
|
|
|
|
**/
|
2008-09-08 18:35:21 +00:00
|
|
|
void
|
|
|
|
|
nm_utils_deinit (void)
|
|
|
|
|
{
|
|
|
|
|
if (initialized) {
|
|
|
|
|
crypto_deinit ();
|
|
|
|
|
initialized = FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ssid helpers */
|
|
|
|
|
|
2008-11-20 20:17:01 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ssid_to_utf8:
|
2011-02-23 11:24:58 -06:00
|
|
|
* @ssid: a byte array containing the SSID data
|
2008-11-20 20:17:01 +00:00
|
|
|
*
|
|
|
|
|
* WiFi SSIDs are byte arrays, they are _not_ strings. Thus, an SSID may
|
|
|
|
|
* contain embedded NULLs and other unprintable characters. Often it is
|
|
|
|
|
* useful to print the SSID out for debugging purposes, but that should be the
|
|
|
|
|
* _only_ use of this function. Do not use this function for any persistent
|
|
|
|
|
* storage of the SSID, since the printable SSID returned from this function
|
|
|
|
|
* cannot be converted back into the real SSID of the access point.
|
|
|
|
|
*
|
|
|
|
|
* This function does almost everything humanly possible to convert the input
|
|
|
|
|
* into a printable UTF-8 string, using roughly the following procedure:
|
|
|
|
|
*
|
|
|
|
|
* 1) if the input data is already UTF-8 safe, no conversion is performed
|
|
|
|
|
* 2) attempts to get the current system language from the LANG environment
|
|
|
|
|
* variable, and depending on the language, uses a table of alternative
|
|
|
|
|
* encodings to try. For example, if LANG=hu_HU, the table may first try
|
|
|
|
|
* the ISO-8859-2 encoding, and if that fails, try the Windows-1250 encoding.
|
|
|
|
|
* If all fallback encodings fail, replaces non-UTF-8 characters with '?'.
|
|
|
|
|
* 3) If the system language was unable to be determined, falls back to the
|
|
|
|
|
* ISO-8859-1 encoding, then to the Windows-1251 encoding.
|
|
|
|
|
* 4) If step 3 fails, replaces non-UTF-8 characters with '?'.
|
|
|
|
|
*
|
|
|
|
|
* Again, this function should be used for debugging and display purposes
|
|
|
|
|
* _only_.
|
|
|
|
|
*
|
2011-02-23 11:24:58 -06:00
|
|
|
* Returns: (transfer full): an allocated string containing a UTF-8
|
|
|
|
|
* representation of the SSID, which must be freed by the caller using g_free().
|
|
|
|
|
* Returns NULL on errors.
|
2008-11-20 20:17:01 +00:00
|
|
|
**/
|
2008-07-17 17:15:38 +00:00
|
|
|
char *
|
2011-02-23 11:24:58 -06:00
|
|
|
nm_utils_ssid_to_utf8 (const GByteArray *ssid)
|
2008-07-17 17:15:38 +00:00
|
|
|
{
|
2011-02-23 11:24:58 -06:00
|
|
|
char *converted = NULL;
|
|
|
|
|
char *lang, *e1 = NULL, *e2 = NULL, *e3 = NULL;
|
2008-07-17 17:15:38 +00:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (ssid != NULL, NULL);
|
|
|
|
|
|
2011-02-23 11:24:58 -06:00
|
|
|
if (g_utf8_validate ((const gchar *) ssid->data, ssid->len, NULL))
|
|
|
|
|
return g_strndup ((const gchar *) ssid->data, ssid->len);
|
|
|
|
|
|
|
|
|
|
/* LANG may be a good encoding hint */
|
|
|
|
|
g_get_charset ((const char **)(&e1));
|
|
|
|
|
if ((lang = getenv ("LANG"))) {
|
|
|
|
|
char * dot;
|
|
|
|
|
|
|
|
|
|
lang = g_ascii_strdown (lang, -1);
|
|
|
|
|
if ((dot = strchr (lang, '.')))
|
|
|
|
|
*dot = '\0';
|
|
|
|
|
|
|
|
|
|
get_encodings_for_lang (lang, &e1, &e2, &e3);
|
|
|
|
|
g_free (lang);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
converted = g_convert ((const gchar *) ssid->data, ssid->len, "UTF-8", e1, NULL, NULL, NULL);
|
|
|
|
|
if (!converted && e2)
|
|
|
|
|
converted = g_convert ((const gchar *) ssid->data, ssid->len, "UTF-8", e2, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
if (!converted && e3)
|
|
|
|
|
converted = g_convert ((const gchar *) ssid->data, ssid->len, "UTF-8", e3, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
if (!converted) {
|
|
|
|
|
converted = g_convert_with_fallback ((const gchar *) ssid->data, ssid->len,
|
|
|
|
|
"UTF-8", e1, "?", NULL, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-25 22:07:40 +00:00
|
|
|
return converted;
|
2007-10-09 10:04:07 +00:00
|
|
|
}
|
|
|
|
|
|
2007-10-09 08:57:35 +00:00
|
|
|
/* Shamelessly ripped from the Linux kernel ieee80211 stack */
|
2008-11-20 20:17:01 +00:00
|
|
|
/**
|
2010-05-26 01:20:20 -07:00
|
|
|
* nm_utils_is_empty_ssid:
|
2008-11-20 20:17:01 +00:00
|
|
|
* @ssid: pointer to a buffer containing the SSID data
|
|
|
|
|
* @len: length of the SSID data in @ssid
|
|
|
|
|
*
|
|
|
|
|
* Different manufacturers use different mechanisms for not broadcasting the
|
|
|
|
|
* AP's SSID. This function attempts to detect blank/empty SSIDs using a
|
|
|
|
|
* number of known SSID-cloaking methods.
|
|
|
|
|
*
|
|
|
|
|
* Returns: TRUE if the SSID is "empty", FALSE if it is not
|
|
|
|
|
**/
|
2007-10-09 08:57:35 +00:00
|
|
|
gboolean
|
2007-10-09 10:04:07 +00:00
|
|
|
nm_utils_is_empty_ssid (const guint8 * ssid, int len)
|
2007-09-12 16:23:53 +00:00
|
|
|
{
|
2007-10-09 08:57:35 +00:00
|
|
|
/* Single white space is for Linksys APs */
|
|
|
|
|
if (len == 1 && ssid[0] == ' ')
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
/* Otherwise, if the entire ssid is 0, we assume it is hidden */
|
|
|
|
|
while (len--) {
|
|
|
|
|
if (ssid[len] != '\0')
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
2007-09-12 16:23:53 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-29 17:09:27 -05:00
|
|
|
#define ESSID_MAX_SIZE 32
|
|
|
|
|
|
2008-11-20 20:17:01 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_escape_ssid:
|
|
|
|
|
* @ssid: pointer to a buffer containing the SSID data
|
|
|
|
|
* @len: length of the SSID data in @ssid
|
|
|
|
|
*
|
|
|
|
|
* This function does a quick printable character conversion of the SSID, simply
|
|
|
|
|
* replacing embedded NULLs and non-printable characters with the hexadecimal
|
|
|
|
|
* representation of that character. Intended for debugging only, should not
|
|
|
|
|
* be used for display of SSIDs.
|
|
|
|
|
*
|
|
|
|
|
* Returns: pointer to the escaped SSID, which uses an internal static buffer
|
|
|
|
|
* and will be overwritten by subsequent calls to this function
|
|
|
|
|
**/
|
2007-10-09 08:57:35 +00:00
|
|
|
const char *
|
|
|
|
|
nm_utils_escape_ssid (const guint8 * ssid, guint32 len)
|
2007-09-12 16:23:53 +00:00
|
|
|
{
|
2011-09-29 17:09:27 -05:00
|
|
|
static char escaped[ESSID_MAX_SIZE * 2 + 1];
|
2007-10-09 08:57:35 +00:00
|
|
|
const guint8 *s = ssid;
|
|
|
|
|
char *d = escaped;
|
2007-09-12 16:23:53 +00:00
|
|
|
|
2007-10-09 10:04:07 +00:00
|
|
|
if (nm_utils_is_empty_ssid (ssid, len)) {
|
2007-10-09 08:57:35 +00:00
|
|
|
memcpy (escaped, "<hidden>", sizeof ("<hidden>"));
|
|
|
|
|
return escaped;
|
2007-09-12 16:23:53 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-29 17:09:27 -05:00
|
|
|
len = MIN (len, (guint32) ESSID_MAX_SIZE);
|
2007-10-09 08:57:35 +00:00
|
|
|
while (len--) {
|
|
|
|
|
if (*s == '\0') {
|
|
|
|
|
*d++ = '\\';
|
|
|
|
|
*d++ = '0';
|
|
|
|
|
s++;
|
|
|
|
|
} else {
|
|
|
|
|
*d++ = *s++;
|
2007-09-12 16:23:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
2007-10-09 08:57:35 +00:00
|
|
|
*d = '\0';
|
|
|
|
|
return escaped;
|
2007-09-12 16:23:53 +00:00
|
|
|
}
|
|
|
|
|
|
2008-11-20 20:17:01 +00:00
|
|
|
/**
|
2008-11-23 22:55:03 +00:00
|
|
|
* nm_utils_same_ssid:
|
2008-11-20 20:17:01 +00:00
|
|
|
* @ssid1: first SSID data to compare
|
|
|
|
|
* @ssid2: second SSID data to compare
|
|
|
|
|
* @ignore_trailing_null: TRUE to ignore one trailing NULL byte
|
|
|
|
|
*
|
|
|
|
|
* Earlier versions of the Linux kernel added a NULL byte to the end of the
|
|
|
|
|
* SSID to enable easy printing of the SSID on the console or in a terminal,
|
|
|
|
|
* but this behavior was problematic (SSIDs are simply byte arrays, not strings)
|
|
|
|
|
* and thus was changed. This function compensates for that behavior at the
|
|
|
|
|
* cost of some compatibility with odd SSIDs that may legitimately have trailing
|
|
|
|
|
* NULLs, even though that is functionally pointless.
|
|
|
|
|
*
|
|
|
|
|
* Returns: TRUE if the SSIDs are the same, FALSE if they are not
|
|
|
|
|
**/
|
2007-10-09 08:57:35 +00:00
|
|
|
gboolean
|
|
|
|
|
nm_utils_same_ssid (const GByteArray * ssid1,
|
|
|
|
|
const GByteArray * ssid2,
|
|
|
|
|
gboolean ignore_trailing_null)
|
2007-09-12 16:23:53 +00:00
|
|
|
{
|
2007-10-09 08:57:35 +00:00
|
|
|
guint32 ssid1_len, ssid2_len;
|
|
|
|
|
|
|
|
|
|
if (ssid1 == ssid2)
|
|
|
|
|
return TRUE;
|
|
|
|
|
if ((ssid1 && !ssid2) || (!ssid1 && ssid2))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
ssid1_len = ssid1->len;
|
|
|
|
|
ssid2_len = ssid2->len;
|
|
|
|
|
if (ssid1_len && ssid2_len && ignore_trailing_null) {
|
|
|
|
|
if (ssid1->data[ssid1_len - 1] == '\0')
|
|
|
|
|
ssid1_len--;
|
|
|
|
|
if (ssid2->data[ssid2_len - 1] == '\0')
|
|
|
|
|
ssid2_len--;
|
2007-09-12 16:23:53 +00:00
|
|
|
}
|
|
|
|
|
|
2007-10-09 08:57:35 +00:00
|
|
|
if (ssid1_len != ssid2_len)
|
|
|
|
|
return FALSE;
|
2007-09-12 16:23:53 +00:00
|
|
|
|
2007-10-09 08:57:35 +00:00
|
|
|
return memcmp (ssid1->data, ssid2->data, ssid1_len) == 0 ? TRUE : FALSE;
|
2007-09-12 16:23:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
value_destroy (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
GValue *value = (GValue *) data;
|
|
|
|
|
|
|
|
|
|
g_value_unset (value);
|
|
|
|
|
g_slice_free (GValue, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
value_dup (gpointer key, gpointer val, gpointer user_data)
|
|
|
|
|
{
|
2007-11-26 16:59:47 +00:00
|
|
|
GHashTable *table = (GHashTable *) user_data;
|
2007-09-12 16:23:53 +00:00
|
|
|
GValue *value = (GValue *) val;
|
|
|
|
|
GValue *dup_value;
|
|
|
|
|
|
|
|
|
|
dup_value = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (dup_value, G_VALUE_TYPE (val));
|
|
|
|
|
g_value_copy (value, dup_value);
|
|
|
|
|
|
2007-11-26 16:59:47 +00:00
|
|
|
g_hash_table_insert (table, g_strdup ((char *) key), dup_value);
|
2007-09-12 16:23:53 +00:00
|
|
|
}
|
|
|
|
|
|
2008-11-20 20:17:01 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_gvalue_hash_dup:
|
|
|
|
|
* @hash: a #GHashTable mapping string:GValue
|
|
|
|
|
*
|
|
|
|
|
* Utility function to duplicate a hash table of GValues.
|
|
|
|
|
*
|
2011-01-21 14:46:09 -06:00
|
|
|
* Returns: (transfer container) (element-type utf8 GObject.Value): a newly allocated duplicated #GHashTable, caller must free the
|
2008-11-20 20:17:01 +00:00
|
|
|
* returned hash with g_hash_table_unref() or g_hash_table_destroy()
|
|
|
|
|
**/
|
2007-09-12 16:23:53 +00:00
|
|
|
GHashTable *
|
|
|
|
|
nm_utils_gvalue_hash_dup (GHashTable *hash)
|
|
|
|
|
{
|
2007-11-26 16:59:47 +00:00
|
|
|
GHashTable *table;
|
2007-09-12 16:23:53 +00:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (hash != NULL, NULL);
|
|
|
|
|
|
2007-11-26 16:59:47 +00:00
|
|
|
table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
2007-09-12 16:23:53 +00:00
|
|
|
(GDestroyNotify) g_free,
|
|
|
|
|
value_destroy);
|
|
|
|
|
|
2007-11-26 16:59:47 +00:00
|
|
|
g_hash_table_foreach (hash, value_dup, table);
|
2007-09-12 16:23:53 +00:00
|
|
|
|
2007-11-26 16:59:47 +00:00
|
|
|
return table;
|
2007-09-12 16:23:53 +00:00
|
|
|
}
|
|
|
|
|
|
2008-11-20 20:17:01 +00:00
|
|
|
/**
|
2011-10-13 12:24:04 -04:00
|
|
|
* nm_utils_slist_free: (skip)
|
2008-11-20 20:17:01 +00:00
|
|
|
* @list: a #GSList
|
|
|
|
|
* @elem_destroy_fn: user function called for each element in @list
|
|
|
|
|
*
|
|
|
|
|
* Utility function to free a #GSList.
|
|
|
|
|
**/
|
2007-11-07 16:06:43 +00:00
|
|
|
void
|
|
|
|
|
nm_utils_slist_free (GSList *list, GDestroyNotify elem_destroy_fn)
|
|
|
|
|
{
|
|
|
|
|
if (!list)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (elem_destroy_fn)
|
|
|
|
|
g_slist_foreach (list, (GFunc) elem_destroy_fn, NULL);
|
|
|
|
|
|
|
|
|
|
g_slist_free (list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2008-11-20 20:17:01 +00:00
|
|
|
_nm_utils_string_in_list (const char *str, const char **valid_strings)
|
2007-11-07 16:06:43 +00:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; valid_strings[i]; i++)
|
|
|
|
|
if (strcmp (str, valid_strings[i]) == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
return valid_strings[i] != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2008-11-20 20:17:01 +00:00
|
|
|
_nm_utils_string_slist_validate (GSList *list, const char **valid_values)
|
2007-11-07 16:06:43 +00:00
|
|
|
{
|
|
|
|
|
GSList *iter;
|
|
|
|
|
|
|
|
|
|
for (iter = list; iter; iter = iter->next) {
|
2008-11-20 20:17:01 +00:00
|
|
|
if (!_nm_utils_string_in_list ((char *) iter->data, valid_values))
|
2007-11-07 16:06:43 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-07 12:33:03 -06:00
|
|
|
static void
|
|
|
|
|
_nm_utils_convert_op_to_string (const GValue *src_value, GValue *dest_value)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_OBJECT_PATH));
|
|
|
|
|
|
|
|
|
|
g_value_set_string (dest_value, (const char *) g_value_get_boxed (src_value));
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-07 16:06:43 +00:00
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_strv_to_slist (const GValue *src_value, GValue *dest_value)
|
2007-11-07 16:06:43 +00:00
|
|
|
{
|
|
|
|
|
char **str;
|
|
|
|
|
GSList *list = NULL;
|
|
|
|
|
guint i = 0;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
|
|
|
|
|
|
|
|
|
|
str = (char **) g_value_get_boxed (src_value);
|
|
|
|
|
|
2009-03-27 14:06:23 -04:00
|
|
|
while (str && str[i])
|
2007-11-07 16:06:43 +00:00
|
|
|
list = g_slist_prepend (list, g_strdup (str[i++]));
|
|
|
|
|
|
2007-11-20 22:15:15 +00:00
|
|
|
g_value_take_boxed (dest_value, g_slist_reverse (list));
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-28 10:05:22 -07:00
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_strv_to_ptrarray (const GValue *src_value, GValue *dest_value)
|
2010-07-28 10:05:22 -07:00
|
|
|
{
|
|
|
|
|
char **str;
|
|
|
|
|
GPtrArray *array = NULL;
|
|
|
|
|
guint i = 0;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
|
|
|
|
|
|
|
|
|
|
str = (char **) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
array = g_ptr_array_sized_new (3);
|
|
|
|
|
while (str && str[i])
|
|
|
|
|
g_ptr_array_add (array, g_strdup (str[i++]));
|
|
|
|
|
|
|
|
|
|
g_value_take_boxed (dest_value, array);
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-20 22:15:15 +00:00
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_strv_to_string (const GValue *src_value, GValue *dest_value)
|
2007-11-20 22:15:15 +00:00
|
|
|
{
|
|
|
|
|
GSList *strings;
|
|
|
|
|
GString *printable;
|
|
|
|
|
GSList *iter;
|
|
|
|
|
|
2008-03-29 21:35:41 +00:00
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_LIST_OF_STRING));
|
2007-11-20 22:15:15 +00:00
|
|
|
|
|
|
|
|
strings = (GSList *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
|
|
|
|
for (iter = strings; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
if (iter != strings)
|
|
|
|
|
g_string_append (printable, ", '");
|
|
|
|
|
else
|
|
|
|
|
g_string_append_c (printable, '\'');
|
|
|
|
|
g_string_append (printable, iter->data);
|
|
|
|
|
g_string_append_c (printable, '\'');
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c (printable, ']');
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-26 17:04:32 -07:00
|
|
|
static void
|
2012-02-07 12:33:03 -06:00
|
|
|
_string_array_to_string (const GPtrArray *strings, GValue *dest_value)
|
2010-05-26 17:04:32 -07:00
|
|
|
{
|
|
|
|
|
GString *printable;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
|
|
|
|
for (i = 0; strings && i < strings->len; i++) {
|
|
|
|
|
if (i > 0)
|
|
|
|
|
g_string_append (printable, ", '");
|
|
|
|
|
else
|
|
|
|
|
g_string_append_c (printable, '\'');
|
|
|
|
|
g_string_append (printable, g_ptr_array_index (strings, i));
|
|
|
|
|
g_string_append_c (printable, '\'');
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c (printable, ']');
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-07 12:33:03 -06:00
|
|
|
static void
|
|
|
|
|
_nm_utils_convert_string_array_to_string (const GValue *src_value, GValue *dest_value)
|
|
|
|
|
{
|
|
|
|
|
const GPtrArray *strings;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_STRING));
|
|
|
|
|
|
|
|
|
|
strings = (const GPtrArray *) g_value_get_boxed (src_value);
|
|
|
|
|
_string_array_to_string (strings, dest_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_nm_utils_convert_op_array_to_string (const GValue *src_value, GValue *dest_value)
|
|
|
|
|
{
|
|
|
|
|
const GPtrArray *strings;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH));
|
|
|
|
|
|
|
|
|
|
strings = (const GPtrArray *) g_value_get_boxed (src_value);
|
|
|
|
|
_string_array_to_string (strings, dest_value);
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-20 22:15:15 +00:00
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_uint_array_to_string (const GValue *src_value, GValue *dest_value)
|
2007-11-20 22:15:15 +00:00
|
|
|
{
|
|
|
|
|
GArray *array;
|
|
|
|
|
GString *printable;
|
|
|
|
|
guint i = 0;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UINT_ARRAY));
|
|
|
|
|
|
|
|
|
|
array = (GArray *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
2008-02-12 20:21:36 +00:00
|
|
|
while (array && (i < array->len)) {
|
2007-11-20 22:15:15 +00:00
|
|
|
char buf[INET_ADDRSTRLEN + 1];
|
|
|
|
|
struct in_addr addr;
|
|
|
|
|
|
|
|
|
|
if (i > 0)
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
|
|
|
|
addr.s_addr = g_array_index (array, guint32, i++);
|
2008-06-26 19:33:13 +00:00
|
|
|
if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN))
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: error converting IP4 address 0x%X",
|
|
|
|
|
__func__, ntohl (addr.s_addr));
|
2007-11-20 22:15:15 +00:00
|
|
|
g_string_append_printf (printable, "%u (%s)", addr.s_addr, buf);
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c (printable, ']');
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_ip4_addr_route_struct_array_to_string (const GValue *src_value, GValue *dest_value)
|
2007-11-20 22:15:15 +00:00
|
|
|
{
|
|
|
|
|
GPtrArray *ptr_array;
|
|
|
|
|
GString *printable;
|
|
|
|
|
guint i = 0;
|
|
|
|
|
|
2008-03-29 21:35:41 +00:00
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT));
|
2007-11-20 22:15:15 +00:00
|
|
|
|
|
|
|
|
ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
2009-03-27 14:06:23 -04:00
|
|
|
while (ptr_array && (i < ptr_array->len)) {
|
2007-11-20 22:15:15 +00:00
|
|
|
GArray *array;
|
|
|
|
|
char buf[INET_ADDRSTRLEN + 1];
|
|
|
|
|
struct in_addr addr;
|
2010-03-29 15:10:25 +02:00
|
|
|
gboolean is_addr; /* array contains address x route */
|
2007-11-20 22:15:15 +00:00
|
|
|
|
|
|
|
|
if (i > 0)
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
g_string_append (printable, "{ ");
|
|
|
|
|
array = (GArray *) g_ptr_array_index (ptr_array, i++);
|
|
|
|
|
if (array->len < 2) {
|
|
|
|
|
g_string_append (printable, "invalid");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2010-03-29 15:10:25 +02:00
|
|
|
is_addr = (array->len < 4);
|
2007-11-20 22:15:15 +00:00
|
|
|
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
|
|
|
|
addr.s_addr = g_array_index (array, guint32, 0);
|
2008-06-26 19:33:13 +00:00
|
|
|
if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN))
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: error converting IP4 address 0x%X",
|
|
|
|
|
__func__, ntohl (addr.s_addr));
|
2010-03-29 15:10:25 +02:00
|
|
|
if (is_addr)
|
|
|
|
|
g_string_append_printf (printable, "ip = %s", buf);
|
|
|
|
|
else
|
|
|
|
|
g_string_append_printf (printable, "dst = %s", buf);
|
2007-11-20 22:15:15 +00:00
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
2009-03-27 11:30:24 -04:00
|
|
|
g_string_append_printf (printable, "px = %u",
|
|
|
|
|
g_array_index (array, guint32, 1));
|
2007-11-20 22:15:15 +00:00
|
|
|
|
|
|
|
|
if (array->len > 2) {
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
|
|
|
|
addr.s_addr = g_array_index (array, guint32, 2);
|
2008-06-26 19:33:13 +00:00
|
|
|
if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN))
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: error converting IP4 address 0x%X",
|
|
|
|
|
__func__, ntohl (addr.s_addr));
|
2010-03-29 15:10:25 +02:00
|
|
|
if (is_addr)
|
|
|
|
|
g_string_append_printf (printable, "gw = %s", buf);
|
|
|
|
|
else
|
|
|
|
|
g_string_append_printf (printable, "nh = %s", buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (array->len > 3) {
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
|
|
|
|
g_string_append_printf (printable, "mt = %u",
|
|
|
|
|
g_array_index (array, guint32, 3));
|
2007-11-20 22:15:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_append (printable, " }");
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c (printable, ']');
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
2007-11-07 16:06:43 +00:00
|
|
|
}
|
|
|
|
|
|
2007-12-05 16:41:09 +00:00
|
|
|
static void
|
2008-08-11 14:54:39 +00:00
|
|
|
convert_one_gvalue_hash_entry (gpointer key, gpointer value, gpointer user_data)
|
2007-12-05 16:41:09 +00:00
|
|
|
{
|
|
|
|
|
GString *printable = (GString *) user_data;
|
|
|
|
|
char *value_as_string;
|
|
|
|
|
|
|
|
|
|
value_as_string = g_strdup_value_contents ((GValue *) value);
|
|
|
|
|
g_string_append_printf (printable, " { '%s': %s },", (const char *) key, value_as_string);
|
|
|
|
|
g_free (value_as_string);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_gvalue_hash_to_string (const GValue *src_value, GValue *dest_value)
|
2007-12-05 16:41:09 +00:00
|
|
|
{
|
|
|
|
|
GHashTable *hash;
|
|
|
|
|
GString *printable;
|
|
|
|
|
|
2008-03-29 21:35:41 +00:00
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_VARIANT));
|
2007-12-05 16:41:09 +00:00
|
|
|
|
|
|
|
|
hash = (GHashTable *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
2008-08-11 14:54:39 +00:00
|
|
|
g_hash_table_foreach (hash, convert_one_gvalue_hash_entry, printable);
|
|
|
|
|
g_string_append (printable, " ]");
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
convert_one_string_hash_entry (gpointer key, gpointer value, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
GString *printable = (GString *) user_data;
|
|
|
|
|
|
|
|
|
|
g_string_append_printf (printable, " { '%s': %s },", (const char *) key, (const char *) value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_string_hash_to_string (const GValue *src_value, GValue *dest_value)
|
2008-08-11 14:54:39 +00:00
|
|
|
{
|
|
|
|
|
GHashTable *hash;
|
|
|
|
|
GString *printable;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_STRING));
|
|
|
|
|
|
|
|
|
|
hash = (GHashTable *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
2010-04-19 15:10:03 -07:00
|
|
|
if (hash)
|
|
|
|
|
g_hash_table_foreach (hash, convert_one_string_hash_entry, printable);
|
2007-12-05 16:41:09 +00:00
|
|
|
g_string_append (printable, " ]");
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-27 11:30:24 -04:00
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_byte_array_to_string (const GValue *src_value, GValue *dest_value)
|
2009-03-27 11:30:24 -04:00
|
|
|
{
|
|
|
|
|
GArray *array;
|
|
|
|
|
GString *printable;
|
|
|
|
|
guint i = 0;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UCHAR_ARRAY));
|
|
|
|
|
|
|
|
|
|
array = (GArray *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
2009-03-27 14:06:23 -04:00
|
|
|
if (array) {
|
|
|
|
|
while (i < MIN (array->len, 35)) {
|
|
|
|
|
if (i > 0)
|
|
|
|
|
g_string_append_c (printable, ' ');
|
|
|
|
|
g_string_append_printf (printable, "0x%02X",
|
|
|
|
|
g_array_index (array, unsigned char, i++));
|
|
|
|
|
}
|
|
|
|
|
if (i < array->len)
|
|
|
|
|
g_string_append (printable, " ... ");
|
2009-03-27 11:30:24 -04:00
|
|
|
}
|
|
|
|
|
g_string_append_c (printable, ']');
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-22 18:59:40 +01:00
|
|
|
static gboolean
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_inet6_ntop (struct in6_addr *addr, char *buf)
|
2010-03-22 18:59:40 +01:00
|
|
|
{
|
|
|
|
|
if (!inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN)) {
|
|
|
|
|
int i;
|
|
|
|
|
GString *ip6_str = g_string_new (NULL);
|
|
|
|
|
g_string_append_printf (ip6_str, "%02X", addr->s6_addr[0]);
|
|
|
|
|
for (i = 1; i < 16; i++)
|
|
|
|
|
g_string_append_printf (ip6_str, " %02X", addr->s6_addr[i]);
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: error converting IP6 address %s",
|
|
|
|
|
__func__, ip6_str->str);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_string_free (ip6_str, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_ip6_dns_array_to_string (const GValue *src_value, GValue *dest_value)
|
2010-03-22 18:59:40 +01:00
|
|
|
{
|
|
|
|
|
GPtrArray *ptr_array;
|
|
|
|
|
GString *printable;
|
|
|
|
|
guint i = 0;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR));
|
|
|
|
|
|
|
|
|
|
ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
|
|
|
|
while (ptr_array && (i < ptr_array->len)) {
|
|
|
|
|
GByteArray *bytearray;
|
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
|
struct in6_addr *addr;
|
|
|
|
|
|
|
|
|
|
if (i > 0)
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
bytearray = (GByteArray *) g_ptr_array_index (ptr_array, i++);
|
|
|
|
|
if (bytearray->len != 16) {
|
|
|
|
|
g_string_append (printable, "invalid");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
addr = (struct in6_addr *) bytearray->data;
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_inet6_ntop (addr, buf);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_string_append_printf (printable, "%s", buf);
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c (printable, ']');
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValue *dest_value)
|
2010-03-22 18:59:40 +01:00
|
|
|
{
|
|
|
|
|
GPtrArray *ptr_array;
|
|
|
|
|
GString *printable;
|
|
|
|
|
guint i = 0;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
|
|
|
|
|
|
|
|
|
|
ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
|
|
|
|
while (ptr_array && (i < ptr_array->len)) {
|
|
|
|
|
GValueArray *elements;
|
|
|
|
|
GValue *tmp;
|
|
|
|
|
GByteArray *ba_addr;
|
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
|
struct in6_addr *addr;
|
|
|
|
|
guint32 prefix;
|
|
|
|
|
|
|
|
|
|
if (i > 0)
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
g_string_append (printable, "{ ");
|
|
|
|
|
elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
|
2010-04-30 15:29:53 -07:00
|
|
|
if ( (elements->n_values != 3)
|
2010-03-22 18:59:40 +01:00
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
|
2010-04-30 15:29:53 -07:00
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) {
|
|
|
|
|
g_string_append (printable, "invalid }");
|
2010-03-22 18:59:40 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* IPv6 address */
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 0);
|
|
|
|
|
ba_addr = g_value_get_boxed (tmp);
|
|
|
|
|
if (ba_addr->len != 16) {
|
2010-04-30 15:29:53 -07:00
|
|
|
g_string_append (printable, "invalid }");
|
2010-03-22 18:59:40 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
addr = (struct in6_addr *) ba_addr->data;
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_inet6_ntop (addr, buf);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_string_append_printf (printable, "ip = %s", buf);
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
/* Prefix */
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 1);
|
|
|
|
|
prefix = g_value_get_uint (tmp);
|
|
|
|
|
if (prefix > 128) {
|
2010-04-30 15:29:53 -07:00
|
|
|
g_string_append (printable, "invalid }");
|
2010-03-22 18:59:40 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
g_string_append_printf (printable, "px = %u", prefix);
|
2010-04-19 10:14:44 -07:00
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
/* IPv6 Gateway */
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 2);
|
|
|
|
|
ba_addr = g_value_get_boxed (tmp);
|
|
|
|
|
if (ba_addr->len != 16) {
|
2010-04-30 15:29:53 -07:00
|
|
|
g_string_append (printable, "invalid }");
|
2010-04-19 10:14:44 -07:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
addr = (struct in6_addr *) ba_addr->data;
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_inet6_ntop (addr, buf);
|
2010-04-19 10:14:44 -07:00
|
|
|
g_string_append_printf (printable, "gw = %s", buf);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_string_append (printable, " }");
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c (printable, ']');
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_ip6_route_struct_array_to_string (const GValue *src_value, GValue *dest_value)
|
2010-03-22 18:59:40 +01:00
|
|
|
{
|
|
|
|
|
GPtrArray *ptr_array;
|
|
|
|
|
GString *printable;
|
|
|
|
|
guint i = 0;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE));
|
|
|
|
|
|
|
|
|
|
ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
|
|
|
|
|
|
|
|
|
|
printable = g_string_new ("[");
|
|
|
|
|
while (ptr_array && (i < ptr_array->len)) {
|
|
|
|
|
GValueArray *elements;
|
|
|
|
|
GValue *tmp;
|
|
|
|
|
GByteArray *ba_addr;
|
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
|
struct in6_addr *addr;
|
|
|
|
|
guint32 prefix, metric;
|
|
|
|
|
|
|
|
|
|
if (i > 0)
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
g_string_append (printable, "{ ");
|
|
|
|
|
elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
|
|
|
|
|
if ( (elements->n_values != 4)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 3)) != G_TYPE_UINT)) {
|
|
|
|
|
g_string_append (printable, "invalid");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Destination address */
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 0);
|
|
|
|
|
ba_addr = g_value_get_boxed (tmp);
|
|
|
|
|
if (ba_addr->len != 16) {
|
|
|
|
|
g_string_append (printable, "invalid");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
addr = (struct in6_addr *) ba_addr->data;
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_inet6_ntop (addr, buf);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_string_append_printf (printable, "dst = %s", buf);
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
/* Prefix */
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 1);
|
|
|
|
|
prefix = g_value_get_uint (tmp);
|
|
|
|
|
if (prefix > 128) {
|
|
|
|
|
g_string_append (printable, "invalid");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
g_string_append_printf (printable, "px = %u", prefix);
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
/* Next hop addresses */
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 2);
|
|
|
|
|
ba_addr = g_value_get_boxed (tmp);
|
|
|
|
|
if (ba_addr->len != 16) {
|
|
|
|
|
g_string_append (printable, "invalid");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
addr = (struct in6_addr *) ba_addr->data;
|
|
|
|
|
memset (buf, 0, sizeof (buf));
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_inet6_ntop (addr, buf);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_string_append_printf (printable, "nh = %s", buf);
|
|
|
|
|
g_string_append (printable, ", ");
|
|
|
|
|
|
|
|
|
|
/* Metric */
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 3);
|
|
|
|
|
metric = g_value_get_uint (tmp);
|
|
|
|
|
g_string_append_printf (printable, "mt = %u", metric);
|
|
|
|
|
|
|
|
|
|
g_string_append (printable, " }");
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c (printable, ']');
|
|
|
|
|
|
|
|
|
|
g_value_take_string (dest_value, printable->str);
|
|
|
|
|
g_string_free (printable, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-19 10:14:44 -07:00
|
|
|
#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
|
|
|
|
|
#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
|
|
|
|
|
|
|
|
|
|
static void
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_old_ip6_addr_array (const GValue *src_value, GValue *dst_value)
|
2010-04-19 10:14:44 -07:00
|
|
|
{
|
|
|
|
|
GPtrArray *src_outer_array;
|
|
|
|
|
GPtrArray *dst_outer_array;
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
|
|
|
|
|
|
|
|
|
|
src_outer_array = (GPtrArray *) g_value_get_boxed (src_value);
|
|
|
|
|
dst_outer_array = g_ptr_array_new ();
|
|
|
|
|
|
|
|
|
|
for (i = 0; src_outer_array && (i < src_outer_array->len); i++) {
|
|
|
|
|
GValueArray *src_addr_array;
|
|
|
|
|
GValueArray *dst_addr_array;
|
|
|
|
|
GValue element = {0, };
|
|
|
|
|
GValue *src_addr, *src_prefix;
|
|
|
|
|
GByteArray *ba;
|
|
|
|
|
|
|
|
|
|
src_addr_array = (GValueArray *) g_ptr_array_index (src_outer_array, i);
|
|
|
|
|
|
|
|
|
|
if ( (src_addr_array->n_values != 2)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 1)) != G_TYPE_UINT)) {
|
|
|
|
|
g_warning ("%s: invalid old IPv6 address type", __func__);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst_addr_array = g_value_array_new (3);
|
|
|
|
|
|
|
|
|
|
src_addr = g_value_array_get_nth (src_addr_array, 0);
|
|
|
|
|
g_value_array_append (dst_addr_array, src_addr);
|
|
|
|
|
src_prefix = g_value_array_get_nth (src_addr_array, 1);
|
|
|
|
|
g_value_array_append (dst_addr_array, src_prefix);
|
|
|
|
|
|
|
|
|
|
/* Blank Gateway */
|
|
|
|
|
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
|
|
|
|
|
ba = g_byte_array_new ();
|
|
|
|
|
g_byte_array_append (ba, (guint8 *) "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
|
|
|
|
|
g_value_take_boxed (&element, ba);
|
|
|
|
|
g_value_array_append (dst_addr_array, &element);
|
|
|
|
|
g_value_unset (&element);
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (dst_outer_array, dst_addr_array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_value_take_boxed (dst_value, dst_outer_array);
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-07 16:06:43 +00:00
|
|
|
void
|
2008-11-20 20:22:14 +00:00
|
|
|
_nm_utils_register_value_transformations (void)
|
2007-11-07 16:06:43 +00:00
|
|
|
{
|
|
|
|
|
static gboolean registered = FALSE;
|
|
|
|
|
|
|
|
|
|
if (G_UNLIKELY (!registered)) {
|
2012-02-07 12:33:03 -06:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_OBJECT_PATH,
|
|
|
|
|
G_TYPE_STRING,
|
|
|
|
|
_nm_utils_convert_op_to_string);
|
2007-11-07 16:06:43 +00:00
|
|
|
g_value_register_transform_func (G_TYPE_STRV,
|
2008-03-29 21:35:41 +00:00
|
|
|
DBUS_TYPE_G_LIST_OF_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_strv_to_slist);
|
2010-07-28 10:05:22 -07:00
|
|
|
g_value_register_transform_func (G_TYPE_STRV,
|
|
|
|
|
DBUS_TYPE_G_ARRAY_OF_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_strv_to_ptrarray);
|
2008-03-29 21:35:41 +00:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
|
2007-11-20 22:15:15 +00:00
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_strv_to_string);
|
2010-05-26 17:04:32 -07:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_STRING,
|
|
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_string_array_to_string);
|
2012-02-07 12:33:03 -06:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
|
|
|
|
|
G_TYPE_STRING,
|
|
|
|
|
_nm_utils_convert_op_array_to_string);
|
2007-11-20 22:15:15 +00:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_UINT_ARRAY,
|
|
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_uint_array_to_string);
|
2008-03-29 21:35:41 +00:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
|
2007-11-20 22:15:15 +00:00
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_ip4_addr_route_struct_array_to_string);
|
2008-03-29 21:35:41 +00:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_VARIANT,
|
2007-12-05 16:41:09 +00:00
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_gvalue_hash_to_string);
|
2008-08-11 14:54:39 +00:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_STRING,
|
|
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_string_hash_to_string);
|
2009-03-27 11:30:24 -04:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_UCHAR_ARRAY,
|
|
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_byte_array_to_string);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR,
|
|
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_ip6_dns_array_to_string);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
|
|
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_ip6_addr_struct_array_to_string);
|
2010-03-22 18:59:40 +01:00
|
|
|
g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
|
|
|
|
|
G_TYPE_STRING,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_ip6_route_struct_array_to_string);
|
2010-04-19 10:14:44 -07:00
|
|
|
g_value_register_transform_func (OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
|
|
|
|
|
DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
|
2011-05-05 12:23:41 -05:00
|
|
|
_nm_utils_convert_old_ip6_addr_array);
|
2007-11-07 16:06:43 +00:00
|
|
|
registered = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-17 21:40:17 +00:00
|
|
|
static gboolean
|
|
|
|
|
device_supports_ap_ciphers (guint32 dev_caps,
|
|
|
|
|
guint32 ap_flags,
|
|
|
|
|
gboolean static_wep)
|
|
|
|
|
{
|
|
|
|
|
gboolean have_pair = FALSE;
|
|
|
|
|
gboolean have_group = FALSE;
|
|
|
|
|
/* Device needs to support at least one pairwise and one group cipher */
|
|
|
|
|
|
|
|
|
|
/* Pairwise */
|
|
|
|
|
if (static_wep) {
|
|
|
|
|
/* Static WEP only uses group ciphers */
|
|
|
|
|
have_pair = TRUE;
|
|
|
|
|
} else {
|
2008-06-10 16:32:39 +00:00
|
|
|
if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40)
|
2007-10-17 21:40:17 +00:00
|
|
|
if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP40)
|
|
|
|
|
have_pair = TRUE;
|
2008-06-10 16:32:39 +00:00
|
|
|
if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104)
|
2007-10-17 21:40:17 +00:00
|
|
|
if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP104)
|
|
|
|
|
have_pair = TRUE;
|
2008-06-10 16:32:39 +00:00
|
|
|
if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)
|
2007-10-17 21:40:17 +00:00
|
|
|
if (ap_flags & NM_802_11_AP_SEC_PAIR_TKIP)
|
|
|
|
|
have_pair = TRUE;
|
2008-06-10 16:32:39 +00:00
|
|
|
if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)
|
2007-10-17 21:40:17 +00:00
|
|
|
if (ap_flags & NM_802_11_AP_SEC_PAIR_CCMP)
|
|
|
|
|
have_pair = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Group */
|
2008-06-10 16:32:39 +00:00
|
|
|
if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40)
|
2007-10-17 21:40:17 +00:00
|
|
|
if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP40)
|
|
|
|
|
have_group = TRUE;
|
2008-06-10 16:32:39 +00:00
|
|
|
if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104)
|
2007-10-17 21:40:17 +00:00
|
|
|
if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP104)
|
|
|
|
|
have_group = TRUE;
|
|
|
|
|
if (!static_wep) {
|
2008-06-10 16:32:39 +00:00
|
|
|
if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)
|
2007-10-17 21:40:17 +00:00
|
|
|
if (ap_flags & NM_802_11_AP_SEC_GROUP_TKIP)
|
|
|
|
|
have_group = TRUE;
|
2008-06-10 16:32:39 +00:00
|
|
|
if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)
|
2007-10-17 21:40:17 +00:00
|
|
|
if (ap_flags & NM_802_11_AP_SEC_GROUP_CCMP)
|
|
|
|
|
have_group = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (have_pair && have_group);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-12 14:38:49 -05:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ap_mode_security_valid:
|
|
|
|
|
* @type: the security type to check AP flags and device capabilties against,
|
|
|
|
|
* e.g. #NMU_SEC_STATIC_WEP
|
|
|
|
|
* @wifi_caps: bitfield of the capabilities of the specific WiFi device, e.g.
|
|
|
|
|
* #NM_WIFI_DEVICE_CAP_CIPHER_WEP40
|
|
|
|
|
*
|
|
|
|
|
* Given a set of device capabilities, and a desired security type to check
|
|
|
|
|
* against, determines whether the combination of device capabilities and
|
|
|
|
|
* desired security type are valid for AP/Hotspot connections.
|
|
|
|
|
*
|
|
|
|
|
* Returns: TRUE if the device capabilities are compatible with the desired
|
|
|
|
|
* @type, FALSE if they are not.
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_utils_ap_mode_security_valid (NMUtilsSecurityType type,
|
|
|
|
|
NMDeviceWifiCapabilities wifi_caps)
|
|
|
|
|
{
|
|
|
|
|
if (!(wifi_caps & NM_WIFI_DEVICE_CAP_AP))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Return TRUE for any security that wpa_supplicant's lightweight AP
|
|
|
|
|
* mode can handle: which is open, WEP, and WPA/WPA2 PSK.
|
|
|
|
|
*/
|
|
|
|
|
switch (type) {
|
|
|
|
|
case NMU_SEC_NONE:
|
|
|
|
|
case NMU_SEC_STATIC_WEP:
|
|
|
|
|
case NMU_SEC_WPA_PSK:
|
|
|
|
|
case NMU_SEC_WPA2_PSK:
|
|
|
|
|
return TRUE;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_security_valid:
|
|
|
|
|
* @type: the security type to check AP flags and device capabilties against,
|
|
|
|
|
* e.g. #NMU_SEC_STATIC_WEP
|
|
|
|
|
* @wifi_caps: bitfield of the capabilities of the specific WiFi device, e.g.
|
|
|
|
|
* #NM_WIFI_DEVICE_CAP_CIPHER_WEP40
|
|
|
|
|
* @have_ap: whether the @ap_flags, @ap_wpa, and @ap_rsn arguments are valid
|
|
|
|
|
* @adhoc: whether the capabilities being tested are from an Ad-Hoc AP (IBSS)
|
|
|
|
|
* @ap_flags: bitfield of AP capabilities, e.g. #NM_802_11_AP_FLAGS_PRIVACY
|
|
|
|
|
* @ap_wpa: bitfield of AP capabilties derived from the AP's WPA beacon,
|
|
|
|
|
* e.g. (#NM_802_11_AP_SEC_PAIR_TKIP | #NM_802_11_AP_SEC_KEY_MGMT_PSK)
|
|
|
|
|
* @ap_rsn: bitfield of AP capabilties derived from the AP's RSN/WPA2 beacon,
|
|
|
|
|
* e.g. (#NM_802_11_AP_SEC_PAIR_CCMP | #NM_802_11_AP_SEC_PAIR_TKIP)
|
|
|
|
|
*
|
|
|
|
|
* Given a set of device capabilities, and a desired security type to check
|
|
|
|
|
* against, determines whether the combination of device, desired security
|
|
|
|
|
* type, and AP capabilities intersect.
|
|
|
|
|
*
|
2012-10-12 14:38:49 -05:00
|
|
|
* NOTE: this function cannot handle checking security for AP/Hotspot mode;
|
|
|
|
|
* use nm_utils_wifi_ap_mode_security_valid() instead.
|
|
|
|
|
*
|
2008-11-20 21:07:03 +00:00
|
|
|
* Returns: TRUE if the device capabilities and AP capabilties intersect and are
|
|
|
|
|
* compatible with the desired @type, FALSE if they are not
|
|
|
|
|
**/
|
2007-10-17 21:40:17 +00:00
|
|
|
gboolean
|
|
|
|
|
nm_utils_security_valid (NMUtilsSecurityType type,
|
2011-08-22 20:23:33 -05:00
|
|
|
NMDeviceWifiCapabilities wifi_caps,
|
2007-10-17 21:40:17 +00:00
|
|
|
gboolean have_ap,
|
2007-12-27 07:17:50 +00:00
|
|
|
gboolean adhoc,
|
2011-08-22 20:23:33 -05:00
|
|
|
NM80211ApFlags ap_flags,
|
|
|
|
|
NM80211ApSecurityFlags ap_wpa,
|
|
|
|
|
NM80211ApSecurityFlags ap_rsn)
|
2007-10-17 21:40:17 +00:00
|
|
|
{
|
|
|
|
|
gboolean good = TRUE;
|
|
|
|
|
|
|
|
|
|
if (!have_ap) {
|
|
|
|
|
if (type == NMU_SEC_NONE)
|
|
|
|
|
return TRUE;
|
|
|
|
|
if ( (type == NMU_SEC_STATIC_WEP)
|
2007-12-27 07:17:50 +00:00
|
|
|
|| ((type == NMU_SEC_DYNAMIC_WEP) && !adhoc)
|
|
|
|
|
|| ((type == NMU_SEC_LEAP) && !adhoc)) {
|
2008-11-20 21:07:03 +00:00
|
|
|
if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104))
|
2007-10-17 21:40:17 +00:00
|
|
|
return TRUE;
|
2012-03-13 15:37:11 +01:00
|
|
|
else
|
|
|
|
|
return FALSE;
|
2007-10-17 21:40:17 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case NMU_SEC_NONE:
|
|
|
|
|
g_assert (have_ap);
|
|
|
|
|
if (ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
|
|
|
|
|
return FALSE;
|
|
|
|
|
if (ap_wpa || ap_rsn)
|
|
|
|
|
return FALSE;
|
|
|
|
|
break;
|
|
|
|
|
case NMU_SEC_LEAP: /* require PRIVACY bit for LEAP? */
|
2007-12-27 07:17:50 +00:00
|
|
|
if (adhoc)
|
|
|
|
|
return FALSE;
|
|
|
|
|
/* Fall through */
|
2007-10-17 21:40:17 +00:00
|
|
|
case NMU_SEC_STATIC_WEP:
|
|
|
|
|
g_assert (have_ap);
|
|
|
|
|
if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
|
|
|
|
|
return FALSE;
|
|
|
|
|
if (ap_wpa || ap_rsn) {
|
2008-11-20 21:07:03 +00:00
|
|
|
if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, TRUE))
|
|
|
|
|
if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, TRUE))
|
2007-10-17 21:40:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NMU_SEC_DYNAMIC_WEP:
|
2007-12-27 07:17:50 +00:00
|
|
|
if (adhoc)
|
|
|
|
|
return FALSE;
|
2007-10-17 21:40:17 +00:00
|
|
|
g_assert (have_ap);
|
|
|
|
|
if (ap_rsn || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
|
|
|
|
|
return FALSE;
|
|
|
|
|
/* Some APs broadcast minimal WPA-enabled beacons that must be handled */
|
|
|
|
|
if (ap_wpa) {
|
|
|
|
|
if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
|
|
|
|
|
return FALSE;
|
2008-11-20 21:07:03 +00:00
|
|
|
if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE))
|
2007-10-17 21:40:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NMU_SEC_WPA_PSK:
|
2012-03-16 17:56:32 -05:00
|
|
|
if (adhoc)
|
|
|
|
|
return FALSE; /* FIXME: Kernel WPA Ad-Hoc support is buggy */
|
2008-11-20 21:07:03 +00:00
|
|
|
if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA))
|
2007-10-17 21:40:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
if (have_ap) {
|
2010-12-16 13:49:28 +01:00
|
|
|
/* Ad-Hoc WPA APs won't necessarily have the PSK flag set, and
|
|
|
|
|
* they don't have any pairwise ciphers. */
|
|
|
|
|
if (adhoc) {
|
|
|
|
|
if ( (ap_wpa & NM_802_11_AP_SEC_GROUP_TKIP)
|
2008-11-20 21:07:03 +00:00
|
|
|
&& (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
|
2007-10-17 21:40:17 +00:00
|
|
|
return TRUE;
|
2010-12-16 13:49:28 +01:00
|
|
|
if ( (ap_wpa & NM_802_11_AP_SEC_GROUP_CCMP)
|
2008-11-20 21:07:03 +00:00
|
|
|
&& (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
|
2007-10-17 21:40:17 +00:00
|
|
|
return TRUE;
|
2010-12-16 13:49:28 +01:00
|
|
|
} else {
|
|
|
|
|
if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) {
|
|
|
|
|
if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP)
|
|
|
|
|
&& (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
|
|
|
|
|
return TRUE;
|
|
|
|
|
if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP)
|
|
|
|
|
&& (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2007-10-17 21:40:17 +00:00
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NMU_SEC_WPA2_PSK:
|
2012-03-16 17:56:32 -05:00
|
|
|
if (adhoc)
|
|
|
|
|
return FALSE; /* FIXME: Kernel WPA Ad-Hoc support is buggy */
|
2008-11-20 21:07:03 +00:00
|
|
|
if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN))
|
2007-10-17 21:40:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
if (have_ap) {
|
2010-12-16 13:49:28 +01:00
|
|
|
/* Ad-Hoc WPA APs won't necessarily have the PSK flag set, and
|
|
|
|
|
* they don't have any pairwise ciphers, nor any RSA flags yet. */
|
|
|
|
|
if (adhoc) {
|
|
|
|
|
if (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)
|
2007-10-17 21:40:17 +00:00
|
|
|
return TRUE;
|
2010-12-16 13:49:28 +01:00
|
|
|
if (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)
|
2007-10-17 21:40:17 +00:00
|
|
|
return TRUE;
|
2010-12-16 13:49:28 +01:00
|
|
|
} else {
|
|
|
|
|
if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) {
|
|
|
|
|
if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP)
|
|
|
|
|
&& (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
|
|
|
|
|
return TRUE;
|
|
|
|
|
if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
|
|
|
|
|
&& (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2007-10-17 21:40:17 +00:00
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NMU_SEC_WPA_ENTERPRISE:
|
2007-12-27 07:17:50 +00:00
|
|
|
if (adhoc)
|
|
|
|
|
return FALSE;
|
2008-11-20 21:07:03 +00:00
|
|
|
if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA))
|
2007-10-17 21:40:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
if (have_ap) {
|
|
|
|
|
if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
|
|
|
|
|
return FALSE;
|
|
|
|
|
/* Ensure at least one WPA cipher is supported */
|
2008-11-20 21:07:03 +00:00
|
|
|
if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE))
|
2007-10-17 21:40:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NMU_SEC_WPA2_ENTERPRISE:
|
2007-12-27 07:17:50 +00:00
|
|
|
if (adhoc)
|
|
|
|
|
return FALSE;
|
2008-11-20 21:07:03 +00:00
|
|
|
if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN))
|
2007-10-17 21:40:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
if (have_ap) {
|
|
|
|
|
if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
|
|
|
|
|
return FALSE;
|
|
|
|
|
/* Ensure at least one WPA cipher is supported */
|
2008-11-20 21:07:03 +00:00
|
|
|
if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, FALSE))
|
2007-10-17 21:40:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
good = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return good;
|
|
|
|
|
}
|
2008-05-06 21:41:08 +00:00
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip4_addresses_from_gvalue:
|
|
|
|
|
* @value: gvalue containing a GPtrArray of GArrays of guint32s
|
|
|
|
|
*
|
|
|
|
|
* Utility function to convert a #GPtrArray of #GArrays of guint32s representing
|
|
|
|
|
* a list of NetworkManager IPv4 addresses (which is a tuple of address, gateway,
|
|
|
|
|
* and prefix) into a GSList of #NMIP4Address objects. The specific format of
|
|
|
|
|
* this serialization is not guaranteed to be stable and the #GArray may be
|
|
|
|
|
* extended in the future.
|
|
|
|
|
*
|
2011-01-21 14:46:09 -06:00
|
|
|
* Returns: (transfer full) (element-type NetworkManager.IP4Address): a newly allocated #GSList of #NMIP4Address objects
|
2008-11-20 21:07:03 +00:00
|
|
|
**/
|
2008-05-06 21:41:08 +00:00
|
|
|
GSList *
|
|
|
|
|
nm_utils_ip4_addresses_from_gvalue (const GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *addresses;
|
|
|
|
|
int i;
|
|
|
|
|
GSList *list = NULL;
|
|
|
|
|
|
|
|
|
|
addresses = (GPtrArray *) g_value_get_boxed (value);
|
|
|
|
|
for (i = 0; addresses && (i < addresses->len); i++) {
|
|
|
|
|
GArray *array = (GArray *) g_ptr_array_index (addresses, i);
|
2008-10-29 14:35:25 +00:00
|
|
|
NMIP4Address *addr;
|
2008-05-06 21:41:08 +00:00
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
if (array->len < 3) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("Ignoring invalid IP4 address");
|
2008-05-06 21:41:08 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-29 14:35:25 +00:00
|
|
|
addr = nm_ip4_address_new ();
|
|
|
|
|
nm_ip4_address_set_address (addr, g_array_index (array, guint32, 0));
|
|
|
|
|
nm_ip4_address_set_prefix (addr, g_array_index (array, guint32, 1));
|
|
|
|
|
nm_ip4_address_set_gateway (addr, g_array_index (array, guint32, 2));
|
2008-05-06 21:41:08 +00:00
|
|
|
list = g_slist_prepend (list, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_slist_reverse (list);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip4_addresses_to_gvalue:
|
2011-10-13 12:24:04 -04:00
|
|
|
* @list: (element-type NMIP4Address): a list of #NMIP4Address objects
|
2008-11-20 21:07:03 +00:00
|
|
|
* @value: a pointer to a #GValue into which to place the converted addresses,
|
|
|
|
|
* which should be unset by the caller (when no longer needed) with
|
|
|
|
|
* g_value_unset().
|
|
|
|
|
*
|
|
|
|
|
* Utility function to convert a #GSList of #NMIP4Address objects into a
|
|
|
|
|
* GPtrArray of GArrays of guint32s representing a list of NetworkManager IPv4
|
|
|
|
|
* addresses (which is a tuple of address, gateway, and prefix). The specific
|
|
|
|
|
* format of this serialization is not guaranteed to be stable and may be
|
|
|
|
|
* extended in the future.
|
|
|
|
|
**/
|
2008-05-06 21:41:08 +00:00
|
|
|
void
|
|
|
|
|
nm_utils_ip4_addresses_to_gvalue (GSList *list, GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *addresses;
|
|
|
|
|
GSList *iter;
|
|
|
|
|
|
|
|
|
|
addresses = g_ptr_array_new ();
|
|
|
|
|
|
|
|
|
|
for (iter = list; iter; iter = iter->next) {
|
2008-10-29 14:35:25 +00:00
|
|
|
NMIP4Address *addr = (NMIP4Address *) iter->data;
|
2008-05-06 21:41:08 +00:00
|
|
|
GArray *array;
|
2008-10-29 14:35:25 +00:00
|
|
|
guint32 tmp;
|
2008-05-06 21:41:08 +00:00
|
|
|
|
|
|
|
|
array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);
|
|
|
|
|
|
2008-10-29 14:35:25 +00:00
|
|
|
tmp = nm_ip4_address_get_address (addr);
|
|
|
|
|
g_array_append_val (array, tmp);
|
|
|
|
|
|
|
|
|
|
tmp = nm_ip4_address_get_prefix (addr);
|
|
|
|
|
g_array_append_val (array, tmp);
|
|
|
|
|
|
|
|
|
|
tmp = nm_ip4_address_get_gateway (addr);
|
|
|
|
|
g_array_append_val (array, tmp);
|
|
|
|
|
|
2008-05-06 21:41:08 +00:00
|
|
|
g_ptr_array_add (addresses, array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_value_take_boxed (value, addresses);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip4_routes_from_gvalue:
|
|
|
|
|
* @value: gvalue containing a GPtrArray of GArrays of guint32s
|
|
|
|
|
*
|
|
|
|
|
* Utility function to convert a GPtrArray of GArrays of guint32s representing
|
|
|
|
|
* a list of NetworkManager IPv4 routes (which is a tuple of route, next hop,
|
|
|
|
|
* prefix, and metric) into a GSList of #NMIP4Route objects. The specific
|
|
|
|
|
* format of this serialization is not guaranteed to be stable and may be
|
|
|
|
|
* extended in the future.
|
|
|
|
|
*
|
2011-01-21 14:46:09 -06:00
|
|
|
* Returns: (transfer full) (element-type NetworkManager.IP4Route): a newly allocated #GSList of #NMIP4Route objects
|
2008-11-20 21:07:03 +00:00
|
|
|
**/
|
2008-08-06 22:23:48 +00:00
|
|
|
GSList *
|
|
|
|
|
nm_utils_ip4_routes_from_gvalue (const GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *routes;
|
|
|
|
|
int i;
|
|
|
|
|
GSList *list = NULL;
|
|
|
|
|
|
|
|
|
|
routes = (GPtrArray *) g_value_get_boxed (value);
|
|
|
|
|
for (i = 0; routes && (i < routes->len); i++) {
|
|
|
|
|
GArray *array = (GArray *) g_ptr_array_index (routes, i);
|
2008-10-29 14:35:25 +00:00
|
|
|
NMIP4Route *route;
|
2008-08-06 22:23:48 +00:00
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
if (array->len < 4) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("Ignoring invalid IP4 route");
|
2008-08-06 22:23:48 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-29 14:35:25 +00:00
|
|
|
route = nm_ip4_route_new ();
|
|
|
|
|
nm_ip4_route_set_dest (route, g_array_index (array, guint32, 0));
|
|
|
|
|
nm_ip4_route_set_prefix (route, g_array_index (array, guint32, 1));
|
|
|
|
|
nm_ip4_route_set_next_hop (route, g_array_index (array, guint32, 2));
|
|
|
|
|
nm_ip4_route_set_metric (route, g_array_index (array, guint32, 3));
|
2008-08-06 22:23:48 +00:00
|
|
|
list = g_slist_prepend (list, route);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_slist_reverse (list);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip4_routes_to_gvalue:
|
2011-10-13 12:24:04 -04:00
|
|
|
* @list: (element-type NMIP4Route): a list of #NMIP4Route objects
|
2008-11-20 21:07:03 +00:00
|
|
|
* @value: a pointer to a #GValue into which to place the converted routes,
|
|
|
|
|
* which should be unset by the caller (when no longer needed) with
|
|
|
|
|
* g_value_unset().
|
|
|
|
|
*
|
|
|
|
|
* Utility function to convert a #GSList of #NMIP4Route objects into a
|
|
|
|
|
* GPtrArray of GArrays of guint32s representing a list of NetworkManager IPv4
|
|
|
|
|
* routes (which is a tuple of route, next hop, prefix, and metric). The
|
|
|
|
|
* specific format of this serialization is not guaranteed to be stable and may
|
|
|
|
|
* be extended in the future.
|
|
|
|
|
**/
|
2008-08-06 22:23:48 +00:00
|
|
|
void
|
|
|
|
|
nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *routes;
|
|
|
|
|
GSList *iter;
|
|
|
|
|
|
|
|
|
|
routes = g_ptr_array_new ();
|
|
|
|
|
|
|
|
|
|
for (iter = list; iter; iter = iter->next) {
|
2008-10-29 14:35:25 +00:00
|
|
|
NMIP4Route *route = (NMIP4Route *) iter->data;
|
2008-08-06 22:23:48 +00:00
|
|
|
GArray *array;
|
2008-10-29 14:35:25 +00:00
|
|
|
guint32 tmp;
|
2008-08-06 22:23:48 +00:00
|
|
|
|
|
|
|
|
array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);
|
|
|
|
|
|
2008-10-29 14:35:25 +00:00
|
|
|
tmp = nm_ip4_route_get_dest (route);
|
|
|
|
|
g_array_append_val (array, tmp);
|
|
|
|
|
|
|
|
|
|
tmp = nm_ip4_route_get_prefix (route);
|
|
|
|
|
g_array_append_val (array, tmp);
|
|
|
|
|
|
|
|
|
|
tmp = nm_ip4_route_get_next_hop (route);
|
|
|
|
|
g_array_append_val (array, tmp);
|
|
|
|
|
|
|
|
|
|
tmp = nm_ip4_route_get_metric (route);
|
|
|
|
|
g_array_append_val (array, tmp);
|
|
|
|
|
|
2008-08-06 22:23:48 +00:00
|
|
|
g_ptr_array_add (routes, array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_value_take_boxed (value, routes);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip4_netmask_to_prefix:
|
|
|
|
|
* @netmask: an IPv4 netmask in network byte order
|
2008-07-07 18:57:37 +00:00
|
|
|
*
|
2008-11-20 21:07:03 +00:00
|
|
|
* Returns: the CIDR prefix represented by the netmask
|
|
|
|
|
**/
|
2008-07-07 18:57:37 +00:00
|
|
|
guint32
|
|
|
|
|
nm_utils_ip4_netmask_to_prefix (guint32 netmask)
|
|
|
|
|
{
|
|
|
|
|
guchar *p, *end;
|
|
|
|
|
guint32 prefix = 0;
|
|
|
|
|
|
|
|
|
|
p = (guchar *) &netmask;
|
|
|
|
|
end = p + sizeof (guint32);
|
|
|
|
|
|
|
|
|
|
while ((*p == 0xFF) && p < end) {
|
|
|
|
|
prefix += 8;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p < end) {
|
|
|
|
|
guchar v = *p;
|
|
|
|
|
|
|
|
|
|
while (v) {
|
|
|
|
|
prefix++;
|
|
|
|
|
v <<= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return prefix;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip4_prefix_to_netmask:
|
|
|
|
|
* @prefix: a CIDR prefix
|
2008-07-07 18:57:37 +00:00
|
|
|
*
|
2012-08-13 11:00:54 -05:00
|
|
|
* Returns: the netmask represented by the prefix, in network byte order
|
2008-11-20 21:07:03 +00:00
|
|
|
**/
|
2008-07-07 18:57:37 +00:00
|
|
|
guint32
|
|
|
|
|
nm_utils_ip4_prefix_to_netmask (guint32 prefix)
|
|
|
|
|
{
|
|
|
|
|
guint32 msk = 0x80000000;
|
|
|
|
|
guint32 netmask = 0;
|
|
|
|
|
|
|
|
|
|
while (prefix > 0) {
|
|
|
|
|
netmask |= msk;
|
|
|
|
|
msk >>= 1;
|
|
|
|
|
prefix--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (guint32) htonl (netmask);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
|
2010-02-25 16:52:10 -08:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip4_get_default_prefix:
|
|
|
|
|
* @ip: an IPv4 address (in network byte order)
|
|
|
|
|
*
|
|
|
|
|
* When the Internet was originally set up, various ranges of IP addresses were
|
|
|
|
|
* segmented into three network classes: A, B, and C. This function will return
|
|
|
|
|
* a prefix that is associated with the IP address specified defining where it
|
|
|
|
|
* falls in the predefined classes.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the default class prefix for the given IP
|
|
|
|
|
**/
|
|
|
|
|
/* The function is originally from ipcalc.c of Red Hat's initscripts. */
|
|
|
|
|
guint32
|
|
|
|
|
nm_utils_ip4_get_default_prefix (guint32 ip)
|
|
|
|
|
{
|
|
|
|
|
if (((ntohl (ip) & 0xFF000000) >> 24) <= 127)
|
|
|
|
|
return 8; /* Class A - 255.0.0.0 */
|
|
|
|
|
else if (((ntohl (ip) & 0xFF000000) >> 24) <= 191)
|
|
|
|
|
return 16; /* Class B - 255.255.0.0 */
|
|
|
|
|
|
|
|
|
|
return 24; /* Class C - 255.255.255.0 */
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-22 18:59:40 +01:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip6_addresses_from_gvalue:
|
|
|
|
|
* @value: gvalue containing a GPtrArray of GValueArrays of (GArray of guchars) and guint32
|
|
|
|
|
*
|
|
|
|
|
* Utility function to convert a #GPtrArray of #GValueArrays of (#GArray of guchars) and guint32
|
2010-04-17 10:26:53 -07:00
|
|
|
* representing a list of NetworkManager IPv6 addresses (which is a tuple of address,
|
|
|
|
|
* prefix, and gateway), into a GSList of #NMIP6Address objects. The specific format of
|
2010-03-22 18:59:40 +01:00
|
|
|
* this serialization is not guaranteed to be stable and the #GValueArray may be
|
|
|
|
|
* extended in the future.
|
|
|
|
|
*
|
2011-01-21 14:46:09 -06:00
|
|
|
* Returns: (transfer full) (element-type NetworkManager.IP6Address): a newly allocated #GSList of #NMIP6Address objects
|
2010-03-22 18:59:40 +01:00
|
|
|
**/
|
2008-06-26 21:30:33 +00:00
|
|
|
GSList *
|
|
|
|
|
nm_utils_ip6_addresses_from_gvalue (const GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *addresses;
|
|
|
|
|
int i;
|
|
|
|
|
GSList *list = NULL;
|
|
|
|
|
|
|
|
|
|
addresses = (GPtrArray *) g_value_get_boxed (value);
|
|
|
|
|
|
|
|
|
|
for (i = 0; addresses && (i < addresses->len); i++) {
|
|
|
|
|
GValueArray *elements = (GValueArray *) g_ptr_array_index (addresses, i);
|
|
|
|
|
GValue *tmp;
|
2009-06-11 15:52:11 -04:00
|
|
|
GByteArray *ba_addr;
|
2010-04-17 10:26:53 -07:00
|
|
|
GByteArray *ba_gw = NULL;
|
2008-10-30 19:39:51 +00:00
|
|
|
NMIP6Address *addr;
|
2008-06-26 21:30:33 +00:00
|
|
|
guint32 prefix;
|
|
|
|
|
|
2010-04-17 10:26:53 -07:00
|
|
|
if (elements->n_values < 2 || elements->n_values > 3) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 address structure", __func__);
|
2010-04-17 10:26:53 -07:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
|
2009-06-11 15:52:11 -04:00
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 address structure", __func__);
|
2008-06-26 21:30:33 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-17 10:26:53 -07:00
|
|
|
/* Check optional 3rd element (gateway) */
|
|
|
|
|
if ( elements->n_values == 3
|
|
|
|
|
&& (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 address structure", __func__);
|
2010-04-17 10:26:53 -07:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-26 21:30:33 +00:00
|
|
|
tmp = g_value_array_get_nth (elements, 0);
|
|
|
|
|
ba_addr = g_value_get_boxed (tmp);
|
|
|
|
|
if (ba_addr->len != 16) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 address of length %d",
|
2008-06-26 21:30:33 +00:00
|
|
|
__func__, ba_addr->len);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 1);
|
|
|
|
|
prefix = g_value_get_uint (tmp);
|
2008-10-30 21:02:26 +00:00
|
|
|
if (prefix > 128) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 prefix %d",
|
2008-06-26 21:30:33 +00:00
|
|
|
__func__, prefix);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-17 10:26:53 -07:00
|
|
|
if (elements->n_values == 3) {
|
|
|
|
|
tmp = g_value_array_get_nth (elements, 2);
|
|
|
|
|
ba_gw = g_value_get_boxed (tmp);
|
|
|
|
|
if (ba_gw->len != 16) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 gateway address of length %d",
|
2010-04-17 10:26:53 -07:00
|
|
|
__func__, ba_gw->len);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-30 19:39:51 +00:00
|
|
|
addr = nm_ip6_address_new ();
|
|
|
|
|
nm_ip6_address_set_prefix (addr, prefix);
|
|
|
|
|
nm_ip6_address_set_address (addr, (const struct in6_addr *) ba_addr->data);
|
2010-04-17 10:26:53 -07:00
|
|
|
if (ba_gw)
|
|
|
|
|
nm_ip6_address_set_gateway (addr, (const struct in6_addr *) ba_gw->data);
|
|
|
|
|
|
2008-06-26 21:30:33 +00:00
|
|
|
list = g_slist_prepend (list, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_slist_reverse (list);
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-22 18:59:40 +01:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip6_addresses_to_gvalue:
|
2011-10-13 12:24:04 -04:00
|
|
|
* @list: (element-type NMIP6Address): a list of #NMIP6Address objects
|
2010-03-22 18:59:40 +01:00
|
|
|
* @value: a pointer to a #GValue into which to place the converted addresses,
|
|
|
|
|
* which should be unset by the caller (when no longer needed) with
|
|
|
|
|
* g_value_unset().
|
|
|
|
|
*
|
|
|
|
|
* Utility function to convert a #GSList of #NMIP6Address objects into a
|
2010-04-17 10:26:53 -07:00
|
|
|
* GPtrArray of GValueArrays representing a list of NetworkManager IPv6 addresses
|
|
|
|
|
* (which is a tuple of address, prefix, and gateway). The specific format of
|
|
|
|
|
* this serialization is not guaranteed to be stable and may be extended in the
|
|
|
|
|
* future.
|
2010-03-22 18:59:40 +01:00
|
|
|
**/
|
2008-06-26 21:30:33 +00:00
|
|
|
void
|
|
|
|
|
nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *addresses;
|
|
|
|
|
GSList *iter;
|
|
|
|
|
|
|
|
|
|
addresses = g_ptr_array_new ();
|
|
|
|
|
|
|
|
|
|
for (iter = list; iter; iter = iter->next) {
|
2008-10-30 19:39:51 +00:00
|
|
|
NMIP6Address *addr = (NMIP6Address *) iter->data;
|
2009-06-11 15:52:11 -04:00
|
|
|
GValueArray *array;
|
|
|
|
|
GValue element = {0, };
|
|
|
|
|
GByteArray *ba;
|
|
|
|
|
|
2010-04-17 10:26:53 -07:00
|
|
|
array = g_value_array_new (3);
|
2009-06-11 15:52:11 -04:00
|
|
|
|
2010-04-17 10:26:53 -07:00
|
|
|
/* IP address */
|
2009-06-11 15:52:11 -04:00
|
|
|
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
|
|
|
|
|
ba = g_byte_array_new ();
|
|
|
|
|
g_byte_array_append (ba, (guint8 *) nm_ip6_address_get_address (addr), 16);
|
|
|
|
|
g_value_take_boxed (&element, ba);
|
|
|
|
|
g_value_array_append (array, &element);
|
|
|
|
|
g_value_unset (&element);
|
|
|
|
|
|
2010-04-17 10:26:53 -07:00
|
|
|
/* Prefix */
|
2009-06-11 15:52:11 -04:00
|
|
|
g_value_init (&element, G_TYPE_UINT);
|
|
|
|
|
g_value_set_uint (&element, nm_ip6_address_get_prefix (addr));
|
|
|
|
|
g_value_array_append (array, &element);
|
|
|
|
|
g_value_unset (&element);
|
|
|
|
|
|
2010-04-17 10:26:53 -07:00
|
|
|
/* Gateway */
|
|
|
|
|
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
|
|
|
|
|
ba = g_byte_array_new ();
|
|
|
|
|
g_byte_array_append (ba, (guint8 *) nm_ip6_address_get_gateway (addr), 16);
|
|
|
|
|
g_value_take_boxed (&element, ba);
|
|
|
|
|
g_value_array_append (array, &element);
|
|
|
|
|
g_value_unset (&element);
|
|
|
|
|
|
2009-06-11 15:52:11 -04:00
|
|
|
g_ptr_array_add (addresses, array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_value_take_boxed (value, addresses);
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-22 18:59:40 +01:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip6_routes_from_gvalue:
|
|
|
|
|
* @value: gvalue containing a GPtrArray of GValueArrays of (GArray or guchars), guint32,
|
|
|
|
|
* (GArray of guchars), and guint32
|
|
|
|
|
*
|
|
|
|
|
* Utility function GPtrArray of GValueArrays of (GArray or guchars), guint32,
|
|
|
|
|
* (GArray of guchars), and guint32 representing a list of NetworkManager IPv6
|
|
|
|
|
* routes (which is a tuple of destination, prefix, next hop, and metric)
|
|
|
|
|
* into a GSList of #NMIP6Route objects. The specific format of this serialization
|
|
|
|
|
* is not guaranteed to be stable and may be extended in the future.
|
|
|
|
|
*
|
2011-01-21 14:46:09 -06:00
|
|
|
* Returns: (transfer full) (element-type NetworkManager.IP6Route): a newly allocated #GSList of #NMIP6Route objects
|
2010-03-22 18:59:40 +01:00
|
|
|
**/
|
2009-06-11 15:52:11 -04:00
|
|
|
GSList *
|
|
|
|
|
nm_utils_ip6_routes_from_gvalue (const GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *routes;
|
|
|
|
|
int i;
|
|
|
|
|
GSList *list = NULL;
|
|
|
|
|
|
|
|
|
|
routes = (GPtrArray *) g_value_get_boxed (value);
|
|
|
|
|
for (i = 0; routes && (i < routes->len); i++) {
|
|
|
|
|
GValueArray *route_values = (GValueArray *) g_ptr_array_index (routes, i);
|
|
|
|
|
GByteArray *dest, *next_hop;
|
|
|
|
|
guint prefix, metric;
|
|
|
|
|
NMIP6Route *route;
|
|
|
|
|
|
|
|
|
|
if ( (route_values->n_values != 4)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 1)) != G_TYPE_UINT)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)
|
|
|
|
|
|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 3)) != G_TYPE_UINT)) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("Ignoring invalid IP6 route");
|
2009-06-11 15:52:11 -04:00
|
|
|
continue;
|
|
|
|
|
}
|
2008-06-26 21:30:33 +00:00
|
|
|
|
2009-06-11 15:52:11 -04:00
|
|
|
dest = g_value_get_boxed (g_value_array_get_nth (route_values, 0));
|
|
|
|
|
if (dest->len != 16) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 dest address of length %d",
|
2009-06-11 15:52:11 -04:00
|
|
|
__func__, dest->len);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prefix = g_value_get_uint (g_value_array_get_nth (route_values, 1));
|
|
|
|
|
|
|
|
|
|
next_hop = g_value_get_boxed (g_value_array_get_nth (route_values, 2));
|
|
|
|
|
if (next_hop->len != 16) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 next_hop address of length %d",
|
2009-06-11 15:52:11 -04:00
|
|
|
__func__, next_hop->len);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
metric = g_value_get_uint (g_value_array_get_nth (route_values, 3));
|
|
|
|
|
|
|
|
|
|
route = nm_ip6_route_new ();
|
|
|
|
|
nm_ip6_route_set_dest (route, (struct in6_addr *)dest->data);
|
|
|
|
|
nm_ip6_route_set_prefix (route, prefix);
|
|
|
|
|
nm_ip6_route_set_next_hop (route, (struct in6_addr *)next_hop->data);
|
|
|
|
|
nm_ip6_route_set_metric (route, metric);
|
|
|
|
|
list = g_slist_prepend (list, route);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_slist_reverse (list);
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-22 18:59:40 +01:00
|
|
|
/**
|
|
|
|
|
* nm_utils_ip6_routes_to_gvalue:
|
2011-10-13 12:24:04 -04:00
|
|
|
* @list: (element-type NMIP6Route): a list of #NMIP6Route objects
|
2010-03-22 18:59:40 +01:00
|
|
|
* @value: a pointer to a #GValue into which to place the converted routes,
|
|
|
|
|
* which should be unset by the caller (when no longer needed) with
|
|
|
|
|
* g_value_unset().
|
|
|
|
|
*
|
|
|
|
|
* Utility function to convert a #GSList of #NMIP6Route objects into a GPtrArray of
|
|
|
|
|
* GValueArrays of (GArray or guchars), guint32, (GArray of guchars), and guint32
|
|
|
|
|
* representing a list of NetworkManager IPv6 routes (which is a tuple of destination,
|
|
|
|
|
* prefix, next hop, and metric). The specific format of this serialization is not
|
|
|
|
|
* guaranteed to be stable and may be extended in the future.
|
|
|
|
|
**/
|
2009-06-11 15:52:11 -04:00
|
|
|
void
|
|
|
|
|
nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *routes;
|
|
|
|
|
GSList *iter;
|
2008-06-26 21:30:33 +00:00
|
|
|
|
2009-06-11 15:52:11 -04:00
|
|
|
routes = g_ptr_array_new ();
|
|
|
|
|
|
|
|
|
|
for (iter = list; iter; iter = iter->next) {
|
|
|
|
|
NMIP6Route *route = (NMIP6Route *) iter->data;
|
|
|
|
|
GValueArray *array;
|
|
|
|
|
const struct in6_addr *addr;
|
|
|
|
|
GByteArray *ba;
|
|
|
|
|
GValue element = {0, };
|
|
|
|
|
|
|
|
|
|
array = g_value_array_new (4);
|
|
|
|
|
|
|
|
|
|
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
|
|
|
|
|
addr = nm_ip6_route_get_dest (route);
|
|
|
|
|
ba = g_byte_array_new ();
|
|
|
|
|
g_byte_array_append (ba, (guchar *)addr, sizeof (*addr));
|
|
|
|
|
g_value_take_boxed (&element, ba);
|
|
|
|
|
g_value_array_append (array, &element);
|
|
|
|
|
g_value_unset (&element);
|
2008-06-26 21:30:33 +00:00
|
|
|
|
2009-06-11 15:52:11 -04:00
|
|
|
g_value_init (&element, G_TYPE_UINT);
|
|
|
|
|
g_value_set_uint (&element, nm_ip6_route_get_prefix (route));
|
|
|
|
|
g_value_array_append (array, &element);
|
|
|
|
|
g_value_unset (&element);
|
2008-06-26 21:30:33 +00:00
|
|
|
|
2009-06-11 15:52:11 -04:00
|
|
|
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
|
|
|
|
|
addr = nm_ip6_route_get_next_hop (route);
|
|
|
|
|
ba = g_byte_array_new ();
|
|
|
|
|
g_byte_array_append (ba, (guchar *)addr, sizeof (*addr));
|
|
|
|
|
g_value_take_boxed (&element, ba);
|
|
|
|
|
g_value_array_append (array, &element);
|
|
|
|
|
g_value_unset (&element);
|
2008-06-26 21:30:33 +00:00
|
|
|
|
2009-06-11 15:52:11 -04:00
|
|
|
g_value_init (&element, G_TYPE_UINT);
|
|
|
|
|
g_value_set_uint (&element, nm_ip6_route_get_metric (route));
|
|
|
|
|
g_value_array_append (array, &element);
|
2008-06-26 21:30:33 +00:00
|
|
|
g_value_unset (&element);
|
2009-06-11 15:52:11 -04:00
|
|
|
|
|
|
|
|
g_ptr_array_add (routes, array);
|
2008-06-26 21:30:33 +00:00
|
|
|
}
|
|
|
|
|
|
2009-06-11 15:52:11 -04:00
|
|
|
g_value_take_boxed (value, routes);
|
2008-06-26 21:30:33 +00:00
|
|
|
}
|
|
|
|
|
|
2011-01-21 14:46:09 -06:00
|
|
|
/* FIXME: the Posix namespace does not exist, and thus neither does
|
|
|
|
|
the in6_addr struct. Marking (skip) for now */
|
|
|
|
|
/**
|
2012-06-14 13:35:30 -04:00
|
|
|
* nm_utils_ip6_dns_from_gvalue: (skip)
|
2011-01-21 14:46:09 -06:00
|
|
|
* @value: a #GValue
|
|
|
|
|
*
|
|
|
|
|
* Converts a #GValue containing a #GPtrArray of IP6 DNS, represented as
|
|
|
|
|
* #GByteArray<!-- -->s into a #GSList of #in6_addr<!-- -->s.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer full) (element-type Posix.in6_addr): a #GSList of IP6
|
|
|
|
|
* addresses.
|
|
|
|
|
*/
|
2008-06-26 21:30:33 +00:00
|
|
|
GSList *
|
|
|
|
|
nm_utils_ip6_dns_from_gvalue (const GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *dns;
|
|
|
|
|
int i;
|
|
|
|
|
GSList *list = NULL;
|
|
|
|
|
|
|
|
|
|
dns = (GPtrArray *) g_value_get_boxed (value);
|
|
|
|
|
for (i = 0; dns && (i < dns->len); i++) {
|
|
|
|
|
GByteArray *bytearray = (GByteArray *) g_ptr_array_index (dns, i);
|
|
|
|
|
struct in6_addr *addr;
|
|
|
|
|
|
|
|
|
|
if (bytearray->len != 16) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("%s: ignoring invalid IP6 address of length %d",
|
|
|
|
|
__func__, bytearray->len);
|
2008-06-26 21:30:33 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr = g_malloc0 (sizeof (struct in6_addr));
|
|
|
|
|
memcpy (addr->s6_addr, bytearray->data, bytearray->len);
|
|
|
|
|
list = g_slist_prepend (list, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_slist_reverse (list);
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-02 22:37:39 -05:00
|
|
|
/**
|
2012-06-14 13:35:30 -04:00
|
|
|
* nm_utils_ip6_dns_to_gvalue: (skip)
|
2011-05-02 22:37:39 -05:00
|
|
|
* @list: a list of #NMIP6Route objects
|
|
|
|
|
* @value: a pointer to a #GValue into which to place the converted DNS server
|
|
|
|
|
* addresses, which should be unset by the caller (when no longer needed) with
|
|
|
|
|
* g_value_unset().
|
|
|
|
|
*
|
|
|
|
|
* Utility function to convert a #GSList of 'struct in6_addr' structs into a
|
|
|
|
|
* GPtrArray of GByteArrays representing each server's IPv6 addresses in
|
|
|
|
|
* network byte order. The specific format of this serialization is not
|
|
|
|
|
* guaranteed to be stable and may be extended in the future.
|
|
|
|
|
*/
|
2008-06-26 21:30:33 +00:00
|
|
|
void
|
|
|
|
|
nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *dns;
|
|
|
|
|
GSList *iter;
|
|
|
|
|
|
|
|
|
|
dns = g_ptr_array_new ();
|
|
|
|
|
|
|
|
|
|
for (iter = list; iter; iter = iter->next) {
|
|
|
|
|
struct in6_addr *addr = (struct in6_addr *) iter->data;
|
|
|
|
|
GByteArray *bytearray;
|
|
|
|
|
|
|
|
|
|
bytearray = g_byte_array_sized_new (16);
|
|
|
|
|
g_byte_array_append (bytearray, (guint8 *) addr->s6_addr, 16);
|
|
|
|
|
g_ptr_array_add (dns, bytearray);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_value_take_boxed (value, dns);
|
|
|
|
|
}
|
2008-08-27 02:57:21 +00:00
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_uuid_generate:
|
|
|
|
|
*
|
|
|
|
|
* Returns: a newly allocated UUID suitable for use as the #NMSettingConnection
|
|
|
|
|
* object's #NMSettingConnection:id: property. Should be freed with g_free()
|
|
|
|
|
**/
|
2008-08-27 02:57:21 +00:00
|
|
|
char *
|
|
|
|
|
nm_utils_uuid_generate (void)
|
|
|
|
|
{
|
|
|
|
|
uuid_t uuid;
|
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
|
|
buf = g_malloc0 (37);
|
|
|
|
|
uuid_generate_random (uuid);
|
|
|
|
|
uuid_unparse_lower (uuid, &buf[0]);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 21:07:03 +00:00
|
|
|
/**
|
|
|
|
|
* nm_utils_uuid_generate_from_string:
|
|
|
|
|
* @s: a string to use as the seed for the UUID
|
|
|
|
|
*
|
|
|
|
|
* For a given @s, this function will always return the same UUID.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a newly allocated UUID suitable for use as the #NMSettingConnection
|
|
|
|
|
* object's #NMSettingConnection:id: property
|
|
|
|
|
**/
|
2008-08-27 02:57:21 +00:00
|
|
|
char *
|
|
|
|
|
nm_utils_uuid_generate_from_string (const char *s)
|
|
|
|
|
{
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
uuid_t *uuid;
|
|
|
|
|
char *buf = NULL;
|
|
|
|
|
|
2008-09-08 18:35:21 +00:00
|
|
|
if (!nm_utils_init (&error)) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("error initializing crypto: (%d) %s",
|
|
|
|
|
error ? error->code : 0,
|
|
|
|
|
error ? error->message : "unknown");
|
2008-08-27 02:57:21 +00:00
|
|
|
if (error)
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-14 06:46:29 -04:00
|
|
|
uuid = g_malloc0 (sizeof (*uuid));
|
|
|
|
|
if (!crypto_md5_hash (NULL, 0, s, strlen (s), (char *) uuid, sizeof (*uuid), &error)) {
|
2011-02-23 11:42:04 -06:00
|
|
|
g_warning ("error generating UUID: (%d) %s",
|
|
|
|
|
error ? error->code : 0,
|
|
|
|
|
error ? error->message : "unknown");
|
2008-08-27 02:57:21 +00:00
|
|
|
if (error)
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf = g_malloc0 (37);
|
|
|
|
|
uuid_unparse_lower (*uuid, &buf[0]);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
g_free (uuid);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 16:01:50 -07:00
|
|
|
static char *
|
|
|
|
|
make_key (const char *salt,
|
|
|
|
|
const gsize salt_len,
|
|
|
|
|
const char *password,
|
|
|
|
|
gsize *out_len,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
char *key;
|
|
|
|
|
guint32 digest_len = 24; /* DES-EDE3-CBC */
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (salt != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (salt_len >= 8, NULL);
|
|
|
|
|
g_return_val_if_fail (password != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (out_len != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
key = g_malloc0 (digest_len + 1);
|
|
|
|
|
if (!key) {
|
|
|
|
|
g_set_error (error,
|
|
|
|
|
NM_CRYPTO_ERROR,
|
|
|
|
|
NM_CRYPTO_ERR_OUT_OF_MEMORY,
|
|
|
|
|
_("Not enough memory to make encryption key."));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!crypto_md5_hash (salt, salt_len, password, strlen (password), key, digest_len, error)) {
|
|
|
|
|
*out_len = 0;
|
|
|
|
|
memset (key, 0, digest_len);
|
|
|
|
|
g_free (key);
|
|
|
|
|
key = NULL;
|
|
|
|
|
} else
|
|
|
|
|
*out_len = digest_len;
|
|
|
|
|
|
|
|
|
|
return key;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* utils_bin2hexstr
|
|
|
|
|
*
|
|
|
|
|
* Convert a byte-array into a hexadecimal string.
|
|
|
|
|
*
|
|
|
|
|
* Code originally by Alex Larsson <alexl@redhat.com> and
|
|
|
|
|
* copyright Red Hat, Inc. under terms of the LGPL.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static char *
|
|
|
|
|
utils_bin2hexstr (const char *bytes, int len, int final_len)
|
|
|
|
|
{
|
|
|
|
|
static char hex_digits[] = "0123456789abcdef";
|
|
|
|
|
char *result;
|
|
|
|
|
int i;
|
|
|
|
|
gsize buflen = (len * 2) + 1;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (bytes != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (len > 0, NULL);
|
|
|
|
|
g_return_val_if_fail (len < 4096, NULL); /* Arbitrary limit */
|
|
|
|
|
if (final_len > -1)
|
|
|
|
|
g_return_val_if_fail (final_len < buflen, NULL);
|
|
|
|
|
|
|
|
|
|
result = g_malloc0 (buflen);
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
{
|
|
|
|
|
result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
|
|
|
|
|
result[2*i+1] = hex_digits[bytes[i] & 0xf];
|
|
|
|
|
}
|
|
|
|
|
/* Cut converted key off at the correct length for this cipher type */
|
|
|
|
|
if (final_len > -1)
|
|
|
|
|
result[final_len] = '\0';
|
|
|
|
|
else
|
|
|
|
|
result[buflen - 1] = '\0';
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_rsa_key_encrypt:
|
|
|
|
|
* @data: RSA private key data to be encrypted
|
2011-01-21 14:46:09 -06:00
|
|
|
* @in_password: (allow-none): existing password to use, if any
|
|
|
|
|
* @out_password: (out) (allow-none): if @in_password was NULL, a random password will be generated
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 16:01:50 -07:00
|
|
|
* and returned in this argument
|
|
|
|
|
* @error: detailed error information on return, if an error occurred
|
|
|
|
|
*
|
|
|
|
|
* Encrypts the given RSA private key data with the given password (or generates
|
|
|
|
|
* a password if no password was given) and converts the data to PEM format
|
|
|
|
|
* suitable for writing to a file.
|
|
|
|
|
*
|
2011-01-21 14:46:09 -06:00
|
|
|
* Returns: (transfer full): on success, PEM-formatted data suitable for writing to a PEM-formatted
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 16:01:50 -07:00
|
|
|
* certificate/private key file.
|
|
|
|
|
**/
|
|
|
|
|
GByteArray *
|
|
|
|
|
nm_utils_rsa_key_encrypt (const GByteArray *data,
|
|
|
|
|
const char *in_password,
|
|
|
|
|
char **out_password,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
char salt[8];
|
|
|
|
|
char *key = NULL, *enc = NULL, *pw_buf[32];
|
|
|
|
|
gsize key_len = 0, enc_len = 0;
|
|
|
|
|
GString *pem = NULL;
|
|
|
|
|
char *tmp, *tmp_password = NULL;
|
|
|
|
|
int left;
|
|
|
|
|
const char *p;
|
|
|
|
|
GByteArray *ret = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (data != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (data->len > 0, NULL);
|
|
|
|
|
if (out_password)
|
|
|
|
|
g_return_val_if_fail (*out_password == NULL, NULL);
|
|
|
|
|
|
|
|
|
|
/* Make the password if needed */
|
|
|
|
|
if (!in_password) {
|
|
|
|
|
if (!crypto_randomize (pw_buf, sizeof (pw_buf), error))
|
|
|
|
|
return NULL;
|
|
|
|
|
in_password = tmp_password = utils_bin2hexstr ((const char *) pw_buf, sizeof (pw_buf), -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!crypto_randomize (salt, sizeof (salt), error))
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
key = make_key (&salt[0], sizeof (salt), in_password, &key_len, error);
|
|
|
|
|
if (!key)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
enc = crypto_encrypt (CIPHER_DES_EDE3_CBC, data, salt, sizeof (salt), key, key_len, &enc_len, error);
|
|
|
|
|
if (!enc)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
pem = g_string_sized_new (enc_len * 2 + 100);
|
|
|
|
|
if (!pem) {
|
|
|
|
|
g_set_error_literal (error, NM_CRYPTO_ERROR,
|
|
|
|
|
NM_CRYPTO_ERR_OUT_OF_MEMORY,
|
|
|
|
|
_("Could not allocate memory for PEM file creation."));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_append (pem, "-----BEGIN RSA PRIVATE KEY-----\n");
|
|
|
|
|
g_string_append (pem, "Proc-Type: 4,ENCRYPTED\n");
|
|
|
|
|
|
|
|
|
|
/* Convert the salt to a hex string */
|
|
|
|
|
tmp = utils_bin2hexstr ((const char *) salt, sizeof (salt), 16);
|
|
|
|
|
if (!tmp) {
|
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
|
NM_CRYPTO_ERR_OUT_OF_MEMORY,
|
|
|
|
|
_("Could not allocate memory for writing IV to PEM file."));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_append_printf (pem, "DEK-Info: DES-EDE3-CBC,%s\n\n", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
|
|
|
|
|
/* Convert the encrypted key to a base64 string */
|
|
|
|
|
p = tmp = g_base64_encode ((const guchar *) enc, enc_len);
|
|
|
|
|
if (!tmp) {
|
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
|
NM_CRYPTO_ERR_OUT_OF_MEMORY,
|
|
|
|
|
_("Could not allocate memory for writing encrypted key to PEM file."));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
left = strlen (tmp);
|
|
|
|
|
while (left > 0) {
|
|
|
|
|
g_string_append_len (pem, p, (left < 64) ? left : 64);
|
|
|
|
|
g_string_append_c (pem, '\n');
|
|
|
|
|
left -= 64;
|
|
|
|
|
p += 64;
|
|
|
|
|
}
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
|
|
|
|
|
g_string_append (pem, "-----END RSA PRIVATE KEY-----\n");
|
|
|
|
|
|
|
|
|
|
ret = g_byte_array_sized_new (pem->len);
|
|
|
|
|
if (!ret) {
|
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
|
NM_CRYPTO_ERR_OUT_OF_MEMORY,
|
|
|
|
|
_("Could not allocate memory for PEM file data."));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
g_byte_array_append (ret, (const unsigned char *) pem->str, pem->len);
|
|
|
|
|
if (tmp_password && out_password)
|
|
|
|
|
*out_password = g_strdup (tmp_password);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
if (key) {
|
|
|
|
|
memset (key, 0, key_len);
|
|
|
|
|
g_free (key);
|
|
|
|
|
}
|
2009-12-23 11:08:26 -08:00
|
|
|
if (enc) {
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 16:01:50 -07:00
|
|
|
memset (enc, 0, enc_len);
|
|
|
|
|
g_free (enc);
|
|
|
|
|
}
|
|
|
|
|
if (pem)
|
|
|
|
|
g_string_free (pem, TRUE);
|
|
|
|
|
|
|
|
|
|
if (tmp_password) {
|
|
|
|
|
memset (tmp_password, 0, strlen (tmp_password));
|
|
|
|
|
g_free (tmp_password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-16 14:42:06 +02:00
|
|
|
/**
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* Returns: TRUE if the file is PKCS#12, FALSE if it is not
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_utils_file_is_pkcs12 (const char *filename)
|
|
|
|
|
{
|
|
|
|
|
return crypto_is_pkcs12_file (filename, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-31 15:32:13 +02:00
|
|
|
/* Band, channel/frequency stuff for wireless */
|
|
|
|
|
struct cf_pair {
|
|
|
|
|
guint32 chan;
|
|
|
|
|
guint32 freq;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct cf_pair a_table[] = {
|
|
|
|
|
/* A band */
|
|
|
|
|
{ 7, 5035 },
|
|
|
|
|
{ 8, 5040 },
|
|
|
|
|
{ 9, 5045 },
|
|
|
|
|
{ 11, 5055 },
|
|
|
|
|
{ 12, 5060 },
|
|
|
|
|
{ 16, 5080 },
|
|
|
|
|
{ 34, 5170 },
|
|
|
|
|
{ 36, 5180 },
|
|
|
|
|
{ 38, 5190 },
|
|
|
|
|
{ 40, 5200 },
|
|
|
|
|
{ 42, 5210 },
|
|
|
|
|
{ 44, 5220 },
|
|
|
|
|
{ 46, 5230 },
|
|
|
|
|
{ 48, 5240 },
|
|
|
|
|
{ 50, 5250 },
|
|
|
|
|
{ 52, 5260 },
|
|
|
|
|
{ 56, 5280 },
|
|
|
|
|
{ 58, 5290 },
|
|
|
|
|
{ 60, 5300 },
|
|
|
|
|
{ 64, 5320 },
|
|
|
|
|
{ 100, 5500 },
|
|
|
|
|
{ 104, 5520 },
|
|
|
|
|
{ 108, 5540 },
|
|
|
|
|
{ 112, 5560 },
|
|
|
|
|
{ 116, 5580 },
|
|
|
|
|
{ 120, 5600 },
|
|
|
|
|
{ 124, 5620 },
|
|
|
|
|
{ 128, 5640 },
|
|
|
|
|
{ 132, 5660 },
|
|
|
|
|
{ 136, 5680 },
|
|
|
|
|
{ 140, 5700 },
|
|
|
|
|
{ 149, 5745 },
|
|
|
|
|
{ 152, 5760 },
|
|
|
|
|
{ 153, 5765 },
|
|
|
|
|
{ 157, 5785 },
|
|
|
|
|
{ 160, 5800 },
|
|
|
|
|
{ 161, 5805 },
|
|
|
|
|
{ 165, 5825 },
|
|
|
|
|
{ 183, 4915 },
|
|
|
|
|
{ 184, 4920 },
|
|
|
|
|
{ 185, 4925 },
|
|
|
|
|
{ 187, 4935 },
|
|
|
|
|
{ 188, 4945 },
|
|
|
|
|
{ 192, 4960 },
|
|
|
|
|
{ 196, 4980 },
|
|
|
|
|
{ 0, -1 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct cf_pair bg_table[] = {
|
|
|
|
|
/* B/G band */
|
|
|
|
|
{ 1, 2412 },
|
|
|
|
|
{ 2, 2417 },
|
|
|
|
|
{ 3, 2422 },
|
|
|
|
|
{ 4, 2427 },
|
|
|
|
|
{ 5, 2432 },
|
|
|
|
|
{ 6, 2437 },
|
|
|
|
|
{ 7, 2442 },
|
|
|
|
|
{ 8, 2447 },
|
|
|
|
|
{ 9, 2452 },
|
|
|
|
|
{ 10, 2457 },
|
|
|
|
|
{ 11, 2462 },
|
|
|
|
|
{ 12, 2467 },
|
|
|
|
|
{ 13, 2472 },
|
|
|
|
|
{ 14, 2484 },
|
|
|
|
|
{ 0, -1 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_wifi_freq_to_channel:
|
|
|
|
|
* @freq: frequency
|
|
|
|
|
*
|
|
|
|
|
* Utility function to translate a WiFi frequency to its corresponding channel.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the channel represented by the frequency or 0
|
|
|
|
|
**/
|
|
|
|
|
guint32
|
|
|
|
|
nm_utils_wifi_freq_to_channel (guint32 freq)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
if (freq > 4900) {
|
|
|
|
|
while (a_table[i].chan && (a_table[i].freq != freq))
|
|
|
|
|
i++;
|
|
|
|
|
return a_table[i].chan;
|
|
|
|
|
} else {
|
|
|
|
|
while (bg_table[i].chan && (bg_table[i].freq != freq))
|
|
|
|
|
i++;
|
|
|
|
|
return bg_table[i].chan;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_wifi_channel_to_freq:
|
|
|
|
|
* @channel: channel
|
|
|
|
|
* @band: frequency band for wireless ("a" or "bg")
|
|
|
|
|
*
|
|
|
|
|
* Utility function to translate a WiFi channel to its corresponding frequency.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the frequency represented by the channel of the band,
|
|
|
|
|
* or -1 when the freq is invalid, or 0 when the band
|
|
|
|
|
* is invalid
|
|
|
|
|
**/
|
|
|
|
|
guint32
|
|
|
|
|
nm_utils_wifi_channel_to_freq (guint32 channel, const char *band)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
if (!strcmp (band, "a")) {
|
|
|
|
|
while (a_table[i].chan && (a_table[i].chan != channel))
|
|
|
|
|
i++;
|
|
|
|
|
return a_table[i].freq;
|
|
|
|
|
} else if (!strcmp (band, "bg")) {
|
|
|
|
|
while (bg_table[i].chan && (bg_table[i].chan != channel))
|
|
|
|
|
i++;
|
|
|
|
|
return bg_table[i].freq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_wifi_find_next_channel:
|
|
|
|
|
* @channel: current channel
|
|
|
|
|
* @direction: whether going downward (0 or less) or upward (1 or more)
|
|
|
|
|
* @band: frequency band for wireless ("a" or "bg")
|
|
|
|
|
*
|
|
|
|
|
* Utility function to find out next/previous WiFi channel for a channel.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the next channel in the specified direction or 0
|
|
|
|
|
**/
|
|
|
|
|
guint32
|
|
|
|
|
nm_utils_wifi_find_next_channel (guint32 channel, int direction, char *band)
|
|
|
|
|
{
|
|
|
|
|
size_t a_size = sizeof (a_table) / sizeof (struct cf_pair);
|
|
|
|
|
size_t bg_size = sizeof (bg_table) / sizeof (struct cf_pair);
|
|
|
|
|
struct cf_pair *pair = NULL;
|
|
|
|
|
|
|
|
|
|
if (!strcmp (band, "a")) {
|
|
|
|
|
if (channel < a_table[0].chan)
|
|
|
|
|
return a_table[0].chan;
|
|
|
|
|
if (channel > a_table[a_size - 2].chan)
|
|
|
|
|
return a_table[a_size - 2].chan;
|
|
|
|
|
pair = &a_table[0];
|
|
|
|
|
} else if (!strcmp (band, "bg")) {
|
|
|
|
|
if (channel < bg_table[0].chan)
|
|
|
|
|
return bg_table[0].chan;
|
|
|
|
|
if (channel > bg_table[bg_size - 2].chan)
|
|
|
|
|
return bg_table[bg_size - 2].chan;
|
|
|
|
|
pair = &bg_table[0];
|
|
|
|
|
} else {
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (pair->chan) {
|
|
|
|
|
if (channel == pair->chan)
|
|
|
|
|
return channel;
|
|
|
|
|
if ((channel < (pair+1)->chan) && (channel > pair->chan)) {
|
|
|
|
|
if (direction > 0)
|
|
|
|
|
return (pair+1)->chan;
|
|
|
|
|
else
|
|
|
|
|
return pair->chan;
|
|
|
|
|
}
|
|
|
|
|
pair++;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_wifi_is_channel_valid:
|
|
|
|
|
* @channel: channel
|
|
|
|
|
* @band: frequency band for wireless ("a" or "bg")
|
|
|
|
|
*
|
|
|
|
|
* Utility function to verify WiFi channel validity.
|
|
|
|
|
*
|
|
|
|
|
* Returns: TRUE or FALSE
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_utils_wifi_is_channel_valid (guint32 channel, const char *band)
|
|
|
|
|
{
|
|
|
|
|
struct cf_pair *table = NULL;
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
if (!strcmp (band, "a"))
|
|
|
|
|
table = a_table;
|
|
|
|
|
else if (!strcmp (band, "bg"))
|
|
|
|
|
table = bg_table;
|
|
|
|
|
else
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
while (table[i].chan && (table[i].chan != channel))
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
if (table[i].chan != 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
else
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-10 16:00:28 -04:00
|
|
|
/**
|
|
|
|
|
* nm_utils_hwaddr_len:
|
|
|
|
|
* @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
|
|
|
|
|
*
|
|
|
|
|
* Returns the length in octets of a hardware address of type @type.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the length
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
nm_utils_hwaddr_len (int type)
|
|
|
|
|
{
|
|
|
|
|
if (type == ARPHRD_ETHER)
|
|
|
|
|
return ETH_ALEN;
|
|
|
|
|
else if (type == ARPHRD_INFINIBAND)
|
|
|
|
|
return INFINIBAND_ALEN;
|
|
|
|
|
else
|
|
|
|
|
g_return_val_if_reached (-1);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-18 11:11:26 -06:00
|
|
|
/**
|
|
|
|
|
* nm_utils_hwaddr_type:
|
|
|
|
|
* @len: the length of hardware address in bytes
|
|
|
|
|
*
|
|
|
|
|
* Returns the type (either %ARPHRD_ETHER or %ARPHRD_INFINIBAND) of the raw
|
|
|
|
|
* address given its length.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the type, either %ARPHRD_ETHER or %ARPHRD_INFINIBAND, or -1 if
|
|
|
|
|
* the address length was not recognized
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
nm_utils_hwaddr_type (int len)
|
|
|
|
|
{
|
|
|
|
|
if (len == ETH_ALEN)
|
|
|
|
|
return ARPHRD_ETHER;
|
|
|
|
|
else if (len == INFINIBAND_ALEN)
|
|
|
|
|
return ARPHRD_INFINIBAND;
|
|
|
|
|
else
|
|
|
|
|
g_return_val_if_reached (-1);
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-10 16:00:28 -04:00
|
|
|
#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_hwaddr_aton:
|
|
|
|
|
* @asc: the ASCII representation of a hardware address
|
|
|
|
|
* @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
|
|
|
|
|
* @buffer: buffer to store the result into
|
|
|
|
|
*
|
|
|
|
|
* Parses @asc and converts it to binary form in @buffer. See
|
|
|
|
|
* nm_utils_hwaddr_atoba() if you'd rather have the result in a
|
|
|
|
|
* #GByteArray.
|
|
|
|
|
*
|
|
|
|
|
* Return value: @buffer, or %NULL if @asc couldn't be parsed
|
|
|
|
|
*/
|
|
|
|
|
guint8 *
|
|
|
|
|
nm_utils_hwaddr_aton (const char *asc, int type, gpointer buffer)
|
|
|
|
|
{
|
|
|
|
|
const char *in = asc;
|
|
|
|
|
guint8 *out = (guint8 *)buffer;
|
|
|
|
|
int left = nm_utils_hwaddr_len (type);
|
|
|
|
|
|
|
|
|
|
while (left && *in) {
|
2011-11-18 10:24:29 -06:00
|
|
|
guint8 d1 = in[0], d2 = in[1];
|
|
|
|
|
|
2012-09-25 10:44:23 -04:00
|
|
|
if (!g_ascii_isxdigit (d1))
|
2011-10-10 16:00:28 -04:00
|
|
|
return NULL;
|
|
|
|
|
|
2011-11-18 10:24:29 -06:00
|
|
|
/* If there's no leading zero (ie "aa:b:cc") then fake it */
|
2012-09-25 10:44:23 -04:00
|
|
|
if (d2 && g_ascii_isxdigit (d2)) {
|
2011-11-18 10:24:29 -06:00
|
|
|
*out++ = (HEXVAL (d1) << 4) + HEXVAL (d2);
|
|
|
|
|
in += 2;
|
|
|
|
|
} else {
|
|
|
|
|
/* Fake leading zero */
|
|
|
|
|
*out++ = (HEXVAL ('0') << 4) + HEXVAL (d1);
|
|
|
|
|
in += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-10 16:00:28 -04:00
|
|
|
left--;
|
|
|
|
|
if (*in) {
|
|
|
|
|
if (*in != ':')
|
|
|
|
|
return NULL;
|
|
|
|
|
in++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (left == 0 && !*in)
|
|
|
|
|
return buffer;
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_hwaddr_atoba:
|
|
|
|
|
* @asc: the ASCII representation of a hardware address
|
|
|
|
|
* @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
|
|
|
|
|
*
|
|
|
|
|
* Parses @asc and converts it to binary form in a #GByteArray. See
|
|
|
|
|
* nm_utils_hwaddr_aton() if you don't want a #GByteArray.
|
|
|
|
|
*
|
2011-12-22 10:51:27 -06:00
|
|
|
* Return value: (transfer full): a new #GByteArray, or %NULL if @asc couldn't
|
|
|
|
|
* be parsed
|
2011-10-10 16:00:28 -04:00
|
|
|
*/
|
|
|
|
|
GByteArray *
|
|
|
|
|
nm_utils_hwaddr_atoba (const char *asc, int type)
|
|
|
|
|
{
|
|
|
|
|
GByteArray *ba;
|
|
|
|
|
int len = nm_utils_hwaddr_len (type);
|
|
|
|
|
|
|
|
|
|
ba = g_byte_array_sized_new (len);
|
|
|
|
|
ba->len = len;
|
|
|
|
|
if (!nm_utils_hwaddr_aton (asc, type, ba->data)) {
|
|
|
|
|
g_byte_array_unref (ba);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ba;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_hwaddr_ntoa:
|
|
|
|
|
* @addr: a binary hardware address
|
|
|
|
|
* @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
|
|
|
|
|
*
|
|
|
|
|
* Converts @addr to textual form.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the textual form of @addr
|
|
|
|
|
*/
|
|
|
|
|
char *
|
|
|
|
|
nm_utils_hwaddr_ntoa (gconstpointer addr, int type)
|
|
|
|
|
{
|
|
|
|
|
const guint8 *in = addr;
|
|
|
|
|
GString *out = g_string_new (NULL);
|
|
|
|
|
int left = nm_utils_hwaddr_len (type);
|
|
|
|
|
|
|
|
|
|
while (left--) {
|
|
|
|
|
if (out->len)
|
|
|
|
|
g_string_append_c (out, ':');
|
|
|
|
|
g_string_append_printf (out, "%02X", *in++);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_string_free (out, FALSE);
|
|
|
|
|
}
|
2012-05-23 16:19:25 +02:00
|
|
|
|
|
|
|
|
/**
|
2012-09-19 10:36:07 -04:00
|
|
|
* nm_utils_iface_valid_name:
|
2012-05-23 16:19:25 +02:00
|
|
|
* @name: Name of interface
|
|
|
|
|
*
|
|
|
|
|
* This function is a 1:1 copy of the kernel's interface validation
|
|
|
|
|
* function in net/core/dev.c.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if interface name is valid, otherwise %FALSE is returned.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2012-08-29 17:55:03 -05:00
|
|
|
nm_utils_iface_valid_name (const char *name)
|
2012-05-23 16:19:25 +02:00
|
|
|
{
|
2012-08-29 17:55:03 -05:00
|
|
|
g_return_val_if_fail (name != NULL, FALSE);
|
|
|
|
|
|
2012-05-23 16:19:25 +02:00
|
|
|
if (*name == '\0')
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (strlen (name) >= 16)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (!strcmp (name, ".") || !strcmp (name, ".."))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
while (*name) {
|
2012-09-25 10:44:23 -04:00
|
|
|
if (*name == '/' || g_ascii_isspace (*name))
|
2012-05-23 16:19:25 +02:00
|
|
|
return FALSE;
|
|
|
|
|
name++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2012-09-19 10:36:07 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_is_uuid:
|
|
|
|
|
* @str: a string that might be a UUID
|
|
|
|
|
*
|
|
|
|
|
* Checks if @str is a UUID
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if @str is a UUID, %FALSE if not
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_utils_is_uuid (const char *str)
|
|
|
|
|
{
|
|
|
|
|
const char *p = str;
|
|
|
|
|
int num_dashes = 0;
|
|
|
|
|
|
|
|
|
|
while (*p) {
|
|
|
|
|
if (*p == '-')
|
|
|
|
|
num_dashes++;
|
2012-09-25 10:44:23 -04:00
|
|
|
else if (!g_ascii_isxdigit (*p))
|
2012-09-19 10:36:07 -04:00
|
|
|
return FALSE;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (num_dashes == 4) && (p - str == 36);
|
|
|
|
|
}
|