diff options
| author | Michael Biebl <biebl@debian.org> | 2015-01-22 00:29:39 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2015-01-22 00:29:39 +0100 |
| commit | 2c032d8f1c6292c1338a615e6ec40252889ba85c (patch) | |
| tree | 1f77182220b2b0264288ba4a476ab47e5bc48716 /libnm-util/nm-utils.c | |
| parent | 33491bc4279481db8ae47213e34a6d695a0e8830 (diff) | |
Imported Upstream version 1.0.0 upstream/1.0.0
Diffstat (limited to 'libnm-util/nm-utils.c')
| -rw-r--r-- | libnm-util/nm-utils.c | 279 |
1 files changed, 184 insertions, 95 deletions
diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c index 0176d9c3..203803f2 100644 --- a/libnm-util/nm-utils.c +++ b/libnm-util/nm-utils.c @@ -1,11 +1,6 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * Ray Strode <rstrode@redhat.com> - * Dan Williams <dcbw@redhat.com> - * Tambet Ingo <tambet@gmail.com> - * +/* * 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 @@ -21,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * (C) Copyright 2005 - 2013 Red Hat, Inc. + * Copyright 2005 - 2013 Red Hat, Inc. */ #include "config.h" @@ -31,6 +26,10 @@ #include <netinet/ether.h> #include <linux/if_infiniband.h> #include <uuid/uuid.h> +#include <libintl.h> +#include <gmodule.h> +#include <gio/gio.h> +#include <glib/gi18n-lib.h> #include "nm-utils.h" #include "nm-utils-private.h" @@ -38,13 +37,17 @@ #include "nm-dbus-glib-types.h" #include "nm-setting-private.h" #include "crypto.h" +#include "nm-utils-internal.h" + +/* Embed the commit id in the build binary */ +static const char *const __nm_git_sha = STRLEN (NM_GIT_SHA) > 0 ? "NM_GIT_SHA:"NM_GIT_SHA : ""; /** * SECTION:nm-utils * @short_description: Utility functions * @include: nm-utils.h * - * A collection of utility functions for working SSIDs, IP addresses, Wi-Fi + * A collection of utility functions for working with SSIDs, IP addresses, Wi-Fi * access points and devices, among other things. */ @@ -144,7 +147,7 @@ init_lang_to_encodings_hash (void) langToEncodings5 = g_hash_table_new (g_str_hash, g_str_equal); while (enc->lang) { g_hash_table_insert (langToEncodings5, (gpointer) enc->lang, - (gpointer) &enc->encodings); + (gpointer) &enc->encodings); enc++; } } @@ -155,7 +158,7 @@ init_lang_to_encodings_hash (void) langToEncodings2 = g_hash_table_new (g_str_hash, g_str_equal); while (enc->lang) { g_hash_table_insert (langToEncodings2, (gpointer) enc->lang, - (gpointer) &enc->encodings); + (gpointer) &enc->encodings); enc++; } } @@ -184,8 +187,7 @@ get_encodings_for_lang (const char *lang, init_lang_to_encodings_hash (); tmp_lang = g_strdup (lang); - if ((encodings = g_hash_table_lookup (langToEncodings5, tmp_lang))) - { + if ((encodings = g_hash_table_lookup (langToEncodings5, tmp_lang))) { *encoding1 = (char *) encodings->encoding1; *encoding2 = (char *) encodings->encoding2; *encoding3 = (char *) encodings->encoding3; @@ -195,8 +197,7 @@ get_encodings_for_lang (const char *lang, /* 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))) - { + if (!success && (encodings = g_hash_table_lookup (langToEncodings2, tmp_lang))) { *encoding1 = (char *) encodings->encoding1; *encoding2 = (char *) encodings->encoding2; *encoding3 = (char *) encodings->encoding3; @@ -209,25 +210,40 @@ get_encodings_for_lang (const char *lang, /* init, deinit for libnm_util */ +static void __attribute__((constructor)) +_check_symbols (void) +{ + GModule *self; + gpointer func; + + self = g_module_open (NULL, 0); + if (g_module_symbol (self, "nm_device_state_get_type", &func)) + g_error ("libnm symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported"); + g_module_close (self); +} + static gboolean initialized = FALSE; /** * 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. - * + * Initializes libnm-util; should be called when starting any program that + * uses libnm-util. This function can be called more than once. + * * Returns: %TRUE if the initialization was successful, %FALSE on failure. **/ gboolean nm_utils_init (GError **error) { + (void) __nm_git_sha; + if (!initialized) { initialized = TRUE; + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + if (!crypto_init (error)) return FALSE; @@ -239,18 +255,12 @@ nm_utils_init (GError **error) /** * 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. + * No-op. Although this function still exists for ABI compatibility reasons, it + * does not have any effect, and does not ever need to be called. **/ void nm_utils_deinit (void) { - if (initialized) { - crypto_deinit (); - initialized = FALSE; - } } /* ssid helpers */ @@ -340,16 +350,16 @@ nm_utils_ssid_to_utf8 (const GByteArray *ssid) gboolean nm_utils_is_empty_ssid (const guint8 * ssid, int len) { - /* Single white space is for Linksys APs */ - if (len == 1 && ssid[0] == ' ') - return TRUE; + /* 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; + /* Otherwise, if the entire ssid is 0, we assume it is hidden */ + while (len--) { + if (ssid[len] != '\0') + return FALSE; + } + return TRUE; } #define ESSID_MAX_SIZE 32 @@ -475,8 +485,8 @@ nm_utils_gvalue_hash_dup (GHashTable *hash) g_return_val_if_fail (hash != NULL, NULL); table = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - value_destroy); + (GDestroyNotify) g_free, + value_destroy); g_hash_table_foreach (hash, value_dup, table); @@ -675,7 +685,7 @@ nm_utils_security_valid (NMUtilsSecurityType type, || ((type == NMU_SEC_LEAP) && !adhoc)) { if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) return TRUE; - else + else return FALSE; } } @@ -894,7 +904,7 @@ nm_utils_wpa_psk_valid (const char *psk) * this serialization is not guaranteed to be stable and the #GArray may be * extended in the future. * - * Returns: (transfer full) (element-type NetworkManager.IP4Address): a newly allocated #GSList of #NMIP4Address objects + * Returns: (transfer full) (element-type NMIP4Address): a newly allocated #GSList of #NMIP4Address objects **/ GSList * nm_utils_ip4_addresses_from_gvalue (const GValue *value) @@ -912,7 +922,7 @@ nm_utils_ip4_addresses_from_gvalue (const GValue *value) g_warning ("Ignoring invalid IP4 address"); continue; } - + 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)); @@ -976,7 +986,7 @@ nm_utils_ip4_addresses_to_gvalue (GSList *list, GValue *value) * format of this serialization is not guaranteed to be stable and may be * extended in the future. * - * Returns: (transfer full) (element-type NetworkManager.IP4Route): a newly allocated #GSList of #NMIP4Route objects + * Returns: (transfer full) (element-type NMIP4Route): a newly allocated #GSList of #NMIP4Route objects **/ GSList * nm_utils_ip4_routes_from_gvalue (const GValue *value) @@ -1133,7 +1143,7 @@ nm_utils_ip4_get_default_prefix (guint32 ip) * this serialization is not guaranteed to be stable and the #GValueArray may be * extended in the future. * - * Returns: (transfer full) (element-type NetworkManager.IP6Address): a newly allocated #GSList of #NMIP6Address objects + * Returns: (transfer full) (element-type NMIP6Address): a newly allocated #GSList of #NMIP6Address objects **/ GSList * nm_utils_ip6_addresses_from_gvalue (const GValue *value) @@ -1168,7 +1178,7 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value) ba_addr = g_value_get_boxed (tmp); if (ba_addr->len != 16) { g_warning ("%s: ignoring invalid IP6 address of length %d", - __func__, ba_addr->len); + __func__, ba_addr->len); continue; } @@ -1176,7 +1186,7 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value) prefix = g_value_get_uint (tmp); if (prefix > 128) { g_warning ("%s: ignoring invalid IP6 prefix %d", - __func__, prefix); + __func__, prefix); continue; } @@ -1185,7 +1195,7 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value) ba_gw = g_value_get_boxed (tmp); if (ba_gw->len != 16) { g_warning ("%s: ignoring invalid IP6 gateway address of length %d", - __func__, ba_gw->len); + __func__, ba_gw->len); continue; } } @@ -1270,7 +1280,7 @@ nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value) * 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. * - * Returns: (transfer full) (element-type NetworkManager.IP6Route): a newly allocated #GSList of #NMIP6Route objects + * Returns: (transfer full) (element-type NMIP6Route): a newly allocated #GSList of #NMIP6Route objects **/ GSList * nm_utils_ip6_routes_from_gvalue (const GValue *value) @@ -1298,7 +1308,7 @@ nm_utils_ip6_routes_from_gvalue (const GValue *value) dest = g_value_get_boxed (g_value_array_get_nth (route_values, 0)); if (dest->len != 16) { g_warning ("%s: ignoring invalid IP6 dest address of length %d", - __func__, dest->len); + __func__, dest->len); continue; } @@ -1307,7 +1317,7 @@ nm_utils_ip6_routes_from_gvalue (const GValue *value) next_hop = g_value_get_boxed (g_value_array_get_nth (route_values, 2)); if (next_hop->len != 16) { g_warning ("%s: ignoring invalid IP6 next_hop address of length %d", - __func__, next_hop->len); + __func__, next_hop->len); continue; } @@ -1334,7 +1344,7 @@ nm_utils_ip6_routes_from_gvalue (const GValue *value) * Utility function to convert a #GSList of #NMIP6Route objects into a #GPtrArray of * #GValueArrays of (#GArray of #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 + * prefix, next hop, and metric). The specific format of this serialization is not * guaranteed to be stable and may be extended in the future. **/ void @@ -1485,9 +1495,11 @@ char * nm_utils_uuid_generate_from_string (const char *s) { GError *error = NULL; - uuid_t *uuid; + uuid_t uuid; char *buf = NULL; + g_return_val_if_fail (s && *s, NULL); + if (!nm_utils_init (&error)) { g_warning ("error initializing crypto: (%d) %s", error ? error->code : 0, @@ -1497,21 +1509,18 @@ nm_utils_uuid_generate_from_string (const char *s) return NULL; } - uuid = g_malloc0 (sizeof (*uuid)); - if (!crypto_md5_hash (NULL, 0, s, strlen (s), (char *) uuid, sizeof (*uuid), &error)) { + if (!crypto_md5_hash (NULL, 0, s, strlen (s), (char *) uuid, sizeof (uuid), &error)) { g_warning ("error generating UUID: (%d) %s", error ? error->code : 0, error ? error->message : "unknown"); if (error) g_error_free (error); - goto out; + return NULL; } buf = g_malloc0 (37); - uuid_unparse_lower (*uuid, &buf[0]); + uuid_unparse_lower (uuid, &buf[0]); -out: - g_free (uuid); return buf; } @@ -1721,9 +1730,9 @@ nm_utils_rsa_key_encrypt_aes (const GByteArray *data, * nm_utils_file_is_pkcs12: * @filename: name of the file to test * - * Utility function to find out if the @filename is in PKCS#12 format. + * Utility function to find out if the @filename is in PKCS#<!-- -->12 format. * - * Returns: %TRUE if the file is PKCS#12, %FALSE if it is not + * Returns: %TRUE if the file is PKCS#<!-- -->12, %FALSE if it is not **/ gboolean nm_utils_file_is_pkcs12 (const char *filename) @@ -1731,6 +1740,82 @@ nm_utils_file_is_pkcs12 (const char *filename) return crypto_is_pkcs12_file (filename, NULL); } +/**********************************************************************************************/ + +/** + * nm_utils_file_search_in_paths: + * @progname: the helper program name, like "iptables" + * Must be a non-empty string, without path separator (/). + * @try_first: (allow-none): a custom path to try first before searching. + * It is silently ignored if it is empty or not an absolute path. + * @paths: (allow-none): a %NULL terminated list of search paths. + * Can be empty or %NULL, in which case only @try_first is checked. + * @file_test_flags: the flags passed to g_file_test() when searching + * for @progname. Set it to 0 to skip the g_file_test(). + * @predicate: (scope call): if given, pass the file name to this function + * for additional checks. This check is performed after the check for + * @file_test_flags. You cannot omit both @file_test_flags and @predicate. + * @user_data: (closure): (allow-none): user data for @predicate function. + * @error: on failure, a "not found" error using @error_domain and @error_code + * + * Searches for a @progname file in a list of search @paths. + * + * Returns: (transfer none): the full path to the helper, if found, or %NULL if not found. + * The returned string is not owned by the caller, but later + * invocations of the function might overwrite it. + */ +const char * +nm_utils_file_search_in_paths (const char *progname, + const char *try_first, + const char *const *paths, + GFileTest file_test_flags, + NMUtilsFileSearchInPathsPredicate predicate, + gpointer user_data, + GError **error) +{ + GString *tmp; + const char *ret; + + g_return_val_if_fail (!error || !*error, NULL); + g_return_val_if_fail (progname && progname[0] && !strchr (progname, '/'), NULL); + g_return_val_if_fail (file_test_flags || predicate, NULL); + + /* Only consider @try_first if it is a valid, absolute path. This makes + * it simpler to pass in a path from configure checks. */ + if ( try_first + && try_first[0] == '/' + && (file_test_flags == 0 || g_file_test (try_first, file_test_flags)) + && (!predicate || predicate (try_first, user_data))) + return g_intern_string (try_first); + + if (!paths || !*paths) + goto NOT_FOUND; + + tmp = g_string_sized_new (50); + for (; *paths; paths++) { + if (!*paths) + continue; + g_string_append (tmp, *paths); + if (tmp->str[tmp->len - 1] != '/') + g_string_append_c (tmp, '/'); + g_string_append (tmp, progname); + if ( (file_test_flags == 0 || g_file_test (tmp->str, file_test_flags)) + && (!predicate || predicate (tmp->str, user_data))) { + ret = g_intern_string (tmp->str); + g_string_free (tmp, TRUE); + return ret; + } + g_string_set_size (tmp, 0); + } + g_string_free (tmp, TRUE); + +NOT_FOUND: + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("Could not find \"%s\" binary"), progname); + return NULL; +} + +/**********************************************************************************************/ + /* Band, channel/frequency stuff for wireless */ struct cf_pair { guint32 chan; @@ -1899,7 +1984,7 @@ nm_utils_wifi_find_next_channel (guint32 channel, int direction, char *band) if (channel == pair->chan) return channel; if ((channel < (pair+1)->chan) && (channel > pair->chan)) { - if (direction > 0) + if (direction > 0) return (pair+1)->chan; else return pair->chan; @@ -1942,7 +2027,8 @@ nm_utils_wifi_is_channel_valid (guint32 channel, const char *band) /** * nm_utils_hwaddr_len: - * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND + * @type: the type of address; either <literal>ARPHRD_ETHER</literal> or + * <literal>ARPHRD_INFINIBAND</literal> * * Returns the length in octets of a hardware address of type @type. * @@ -1963,11 +2049,12 @@ nm_utils_hwaddr_len (int type) * 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. + * Returns the type (either <literal>ARPHRD_ETHER</literal> or + * <literal>ARPHRD_INFINIBAND</literal>) of the raw address given its length. * - * Return value: the type, either %ARPHRD_ETHER or %ARPHRD_INFINIBAND. - * If the length is unexpected, return -1 (unsupported type/length). + * Return value: the type, either <literal>ARPHRD_ETHER</literal> or + * <literal>ARPHRD_INFINIBAND</literal>. If the length is unexpected, return -1 + * (unsupported type/length). * * Deprecated: This could not be extended to cover other types, since * there is not a one-to-one mapping between types and lengths. This @@ -1992,7 +2079,8 @@ nm_utils_hwaddr_type (int len) /** * nm_utils_hwaddr_aton: * @asc: the ASCII representation of a hardware address - * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND + * @type: the type of address; either <literal>ARPHRD_ETHER</literal> or + * <literal>ARPHRD_INFINIBAND</literal> * @buffer: buffer to store the result into * * Parses @asc and converts it to binary form in @buffer. See @@ -2019,7 +2107,8 @@ nm_utils_hwaddr_aton (const char *asc, int type, gpointer buffer) /** * nm_utils_hwaddr_atoba: * @asc: the ASCII representation of a hardware address - * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND + * @type: the type of address; either <literal>ARPHRD_ETHER</literal> or + * <literal>ARPHRD_INFINIBAND</literal> * * Parses @asc and converts it to binary form in a #GByteArray. See * nm_utils_hwaddr_aton() if you don't want a #GByteArray. @@ -2051,7 +2140,8 @@ nm_utils_hwaddr_atoba (const char *asc, int type) /** * nm_utils_hwaddr_ntoa: * @addr: a binary hardware address - * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND + * @type: the type of address; either <literal>ARPHRD_ETHER</literal> or + * <literal>ARPHRD_INFINIBAND</literal> * * Converts @addr to textual form. * @@ -2235,8 +2325,7 @@ nm_utils_bin2hexstr (const char *bytes, int len, int final_len) g_return_val_if_fail (final_len < buflen, NULL); result = g_malloc0 (buflen); - for (i = 0; i < len; i++) - { + for (i = 0; i < len; i++) { result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf]; result[2*i+1] = hex_digits[bytes[i] & 0xf]; } @@ -2385,13 +2474,14 @@ static char _nm_utils_inet_ntop_buffer[NM_UTILS_INET_ADDRSTRLEN]; /** * nm_utils_inet4_ntop: (skip) * @inaddr: the address that should be converted to string. - * @dst: the destination buffer, it must contain at least %INET_ADDRSTRLEN - * or %NM_UTILS_INET_ADDRSTRLEN characters. If set to %NULL, it will return - * a pointer to an internal, static buffer (shared with nm_utils_inet6_ntop()). - * Beware, that the internal buffer will be overwritten with ever new call - * of nm_utils_inet4_ntop() or nm_utils_inet6_ntop() that does not provied it's - * own @dst buffer. Also, using the internal buffer is not thread safe. When - * in doubt, pass your own @dst buffer to avoid these issues. + * @dst: the destination buffer, it must contain at least + * <literal>INET_ADDRSTRLEN</literal> or %NM_UTILS_INET_ADDRSTRLEN + * characters. If set to %NULL, it will return a pointer to an internal, static + * buffer (shared with nm_utils_inet6_ntop()). Beware, that the internal + * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or + * nm_utils_inet6_ntop() that does not provied it's own @dst buffer. Also, + * using the internal buffer is not thread safe. When in doubt, pass your own + * @dst buffer to avoid these issues. * * Wrapper for inet_ntop. * @@ -2410,13 +2500,14 @@ nm_utils_inet4_ntop (in_addr_t inaddr, char *dst) /** * nm_utils_inet6_ntop: (skip) * @in6addr: the address that should be converted to string. - * @dst: the destination buffer, it must contain at least %INET6_ADDRSTRLEN - * or %NM_UTILS_INET_ADDRSTRLEN characters. If set to %NULL, it will return - * a pointer to an internal, static buffer (shared with nm_utils_inet4_ntop()). - * Beware, that the internal buffer will be overwritten with ever new call - * of nm_utils_inet4_ntop() or nm_utils_inet6_ntop() that does not provied it's - * own @dst buffer. Also, using the internal buffer is not thread safe. When - * in doubt, pass your own @dst buffer to avoid these issues. + * @dst: the destination buffer, it must contain at least + * <literal>INET6_ADDRSTRLEN</literal> or %NM_UTILS_INET_ADDRSTRLEN + * characters. If set to %NULL, it will return a pointer to an internal, static + * buffer (shared with nm_utils_inet4_ntop()). Beware, that the internal + * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or + * nm_utils_inet6_ntop() that does not provied it's own @dst buffer. Also, + * using the internal buffer is not thread safe. When in doubt, pass your own + * @dst buffer to avoid these issues. * * Wrapper for inet_ntop. * @@ -2498,13 +2589,10 @@ nm_utils_check_virtual_device_compatibility (GType virtual_type, GType other_typ /***********************************************************/ -/* Unused prototype to make the compiler happy */ -const NMUtilsPrivateData *nm_util_get_private (void); +/* Unused prototypes to make the compiler happy */ +gconstpointer nm_utils_get_private (void); +gconstpointer nm_util_get_private (void); -static const NMUtilsPrivateData data = { - .nm_setting_ip4_config_get_address_label = nm_setting_ip4_config_get_address_label, - .nm_setting_ip4_config_add_address_with_label = nm_setting_ip4_config_add_address_with_label, -}; /** * nm_utils_get_private: @@ -2516,10 +2604,11 @@ static const NMUtilsPrivateData data = { * * Since: 0.9.10 */ -const NMUtilsPrivateData * +gconstpointer nm_utils_get_private (void) { - return &data; + /* We told you not to use it! */ + g_assert_not_reached (); } /** @@ -2531,9 +2620,9 @@ nm_utils_get_private (void) * * Since: 0.9.10 */ -const NMUtilsPrivateData * +gconstpointer nm_util_get_private (void) { - /* Compat function to preserve ABI */ - return nm_utils_get_private (); + /* We told you not to use it! */ + g_assert_not_reached (); } |