diff options
| author | Sebastien Bacher <seb128@ubuntu.com> | 2018-08-24 11:00:09 +0200 |
|---|---|---|
| committer | Sebastien Bacher <seb128@ubuntu.com> | 2018-08-24 11:06:47 +0200 |
| commit | b7db94545968c37886b7111d8c85f62eb063fbb4 (patch) | |
| tree | 7c2aedd497b1fdcb26bf9d49f98cc63a530baf2e /shared/nm-utils/nm-hash-utils.c | |
| parent | 9d5cdc3adde9e7e57bf5a0e754e563b6a9e8e513 (diff) | |
| parent | caf1db9d6fbc056cc6c76a24574890f6c7895f3d (diff) | |
Import Debian changes 1.12.2-0ubuntu3
network-manager (1.12.2-0ubuntu3) cosmic; urgency=medium
* debian/rules:
- use --with-libnm-glib, the default reversed since that's a legacy
library but we still need it for unity-control-center
network-manager (1.12.2-0ubuntu2) cosmic; urgency=medium
* debian/patches/git-newglib-test.patch:
- backport upstream commit to fix the tests with the new glib
network-manager (1.12.2-0ubuntu1) cosmic; urgency=medium
* New upstream version
* d/p/libnm-register-empty-NMClient-and-NetworkManager-when-loa.patch,
d/p/e91f1a7d2a6b8400b6b331d5b72287dcb5164a39.patch,
d/p/git_thunderbolt_connect.patch:
- removed, those changes are in the new version
* Backport Debian changes
* Update symbols file for libnm0
* Enable iwd support
* Drop version requirements when oldstable ships a newer version
* Drop dh_strip override, the dbgsym migration is done
* Rebase patches
* Make sure the example server.conf is actually installed
* Update install path for plugins, it now includes a version number
* Drop libnl3 build dependency.
Upstream has copied the code directly from libnl3 for the few functions it
needs with a few small modifications.
* Drop libiw build dependency.
Hasn't been needed for a long time and was simply a left over from older
releases.
* Bump Standards-Version to 4.1.5
* Fix compile error due to NM_AVAILABLE_IN_1_12_2 macro (Closes: #905372)
Diffstat (limited to 'shared/nm-utils/nm-hash-utils.c')
| -rw-r--r-- | shared/nm-utils/nm-hash-utils.c | 134 |
1 files changed, 99 insertions, 35 deletions
diff --git a/shared/nm-utils/nm-hash-utils.c b/shared/nm-utils/nm-hash-utils.c index c563140e..4bc12b7c 100644 --- a/shared/nm-utils/nm-hash-utils.c +++ b/shared/nm-utils/nm-hash-utils.c @@ -35,33 +35,77 @@ G_STATIC_ASSERT (sizeof (guint) * HASH_KEY_SIZE_GUINT >= HASH_KEY_SIZE); +static const guint8 *volatile global_seed = NULL; + static const guint8 * -_get_hash_key (void) +_get_hash_key_init (void) { - static const guint8 *volatile global_seed = NULL; + /* the returned hash is aligned to guin64, hence, it is safe + * to use it as guint* or guint64* pointer. */ + static union { + guint8 v8[HASH_KEY_SIZE]; + } g_arr _nm_alignas (guint64); + static gsize g_lock; const guint8 *g; + CSipHash siph_state; + uint64_t h; + guint *p; g = global_seed; - if (G_UNLIKELY (g == NULL)) { - /* the returned hash is aligned to guin64, hence, it is save - * to use it as guint* or guint64* pointer. */ - static union { - guint8 v8[HASH_KEY_SIZE]; - } g_arr _nm_alignas (guint64); - static gsize g_lock; - - if (g_once_init_enter (&g_lock)) { - nm_utils_random_bytes (g_arr.v8, sizeof (g_arr.v8)); - g_atomic_pointer_compare_and_exchange (&global_seed, NULL, g_arr.v8); - g = g_arr.v8; - g_once_init_leave (&g_lock, 1); - } else { - g = global_seed; - nm_assert (g); - } + if (G_LIKELY (g != NULL)) { + nm_assert (g == g_arr.v8); + return g; } - return g; + if (g_once_init_enter (&g_lock)) { + + nm_utils_random_bytes (g_arr.v8, sizeof (g_arr.v8)); + + /* use siphash() of the key-size, to mangle the first guint. Otherwise, + * the first guint has only the entropy that nm_utils_random_bytes() + * generated for the first 4 bytes and relies on a good random generator. */ + c_siphash_init (&siph_state, g_arr.v8); + c_siphash_append (&siph_state, g_arr.v8, sizeof (g_arr.v8)); + h = c_siphash_finalize (&siph_state); + p = (guint *) g_arr.v8; + if (sizeof (guint) < sizeof (h)) + *p = *p ^ ((guint) (h & 0xFFFFFFFFu)) ^ ((guint) (h >> 32)); + else + *p = *p ^ ((guint) (h & 0xFFFFFFFFu)); + + g_atomic_pointer_compare_and_exchange (&global_seed, NULL, g_arr.v8); + g_once_init_leave (&g_lock, 1); + } + + nm_assert (global_seed == g_arr.v8); + return g_arr.v8; +} + +#define _get_hash_key() \ + ({ \ + const guint8 *_g; \ + \ + _g = global_seed; \ + if (G_UNLIKELY (_g == NULL)) \ + _g = _get_hash_key_init (); \ + _g; \ + }) + +guint +nm_hash_static (guint static_seed) +{ + /* note that we only xor the static_seed with the key. + * We don't use siphash, which would mix the bits better. + * Note that this doesn't matter, because static_seed is not + * supposed to be a value that you are hashing (for that, use + * full siphash). + * Instead, different callers may set a different static_seed + * so that nm_hash_str(NULL) != nm_hash_ptr(NULL). + * + * Also, ensure that we don't return zero. + */ + return ((*((const guint *) _get_hash_key ())) ^ static_seed) + ?: static_seed ?: 3679500967u; } void @@ -75,7 +119,7 @@ nm_hash_init (NMHashState *state, guint static_seed) g = _get_hash_key (); memcpy (seed, g, HASH_KEY_SIZE); seed[0] ^= static_seed; - siphash24_init (&state->_state, (const guint8 *) seed); + c_siphash_init (&state->_state, (const guint8 *) seed); } guint @@ -83,11 +127,10 @@ nm_hash_str (const char *str) { NMHashState h; - if (str) { - nm_hash_init (&h, 1867854211u); - nm_hash_update_str (&h, str); - } else - nm_hash_init (&h, 842995561u); + if (!str) + return nm_hash_static (1867854211u); + nm_hash_init (&h, 1867854211u); + nm_hash_update_str (&h, str); return nm_hash_complete (&h); } @@ -100,16 +143,13 @@ nm_str_hash (gconstpointer str) guint nm_hash_ptr (gconstpointer ptr) { - guint h; - - h = ((const guint *) _get_hash_key ())[0]; - - if (sizeof (ptr) <= sizeof (guint)) - h = h ^ ((guint) ((uintptr_t) ptr)); - else - h = h ^ ((guint) (((guint64) (uintptr_t) ptr) >> 32)) ^ ((guint) ((uintptr_t) ptr)); + NMHashState h; - return h ?: 2907677551u; + if (!ptr) + return nm_hash_static (2907677551u); + nm_hash_init (&h, 2907677551u); + nm_hash_update (&h, &ptr, sizeof (ptr)); + return nm_hash_complete (&h); } guint @@ -117,3 +157,27 @@ nm_direct_hash (gconstpointer ptr) { return nm_hash_ptr (ptr); } + +/*****************************************************************************/ + +guint +nm_pstr_hash (gconstpointer p) +{ + const char *const*s = p; + + if (!s) + return nm_hash_static (101061439u); + return nm_hash_str (*s); +} + +gboolean +nm_pstr_equal (gconstpointer a, gconstpointer b) +{ + const char *const*s1 = a; + const char *const*s2 = b; + + return (s1 == s2) + || ( s1 + && s2 + && nm_streq0 (*s1, *s2)); +} |