1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
commit 0bf0ee7136dff2b9a6435221987f447e11eea285
Author: Dan Williams <dcbw@redhat.com>
Date: Fri Mar 15 16:49:39 2013 -0500
dhcp: look harder for machine-id, and generate random DUID if it doesn't exist (bgo #696109)
Not all systems have machine-id in /etc, some still have it in /var/lib/dbus/
especially if they aren't using systemd. Furthermore, if we don't have
any machine-id file (like in the future, if we don't have a messaebus
daemon running) fall back to a random DUID as a last resort.
Index: network-manager/src/dhcp-manager/nm-dhcp-client.c
===================================================================
--- network-manager.orig/src/dhcp-manager/nm-dhcp-client.c 2013-05-08 20:19:08.998435531 +0200
+++ network-manager/src/dhcp-manager/nm-dhcp-client.c 2013-05-08 20:19:08.994435487 +0200
@@ -354,40 +354,44 @@
{
GByteArray *duid;
char *contents = NULL;
- GError *error = NULL;
GChecksum *sum;
guint8 buffer[32]; /* SHA256 digest size */
gsize sumlen = sizeof (buffer);
const guint16 duid_type = g_htons (4);
uuid_t uuid;
- gboolean success;
+ GRand *rand;
+ guint i;
+ gboolean success = FALSE;
/* Get the machine ID from /etc/machine-id; it's always in /etc no matter
- * where our configured SYSCONFDIR is.
+ * where our configured SYSCONFDIR is. Alternatively, it might be in
+ * LOCALSTATEDIR /lib/dbus/machine-id.
*/
- if (!g_file_get_contents ("/etc/machine-id", &contents, NULL, &error)) {
- nm_log_warn (LOGD_DHCP6, "Failed to read " SYSCONFDIR "/machine-id to generate DHCPv6 DUID: (%d) %s",
- error ? error->code : -1,
- error ? error->message : "(unknown)");
- g_clear_error (&error);
- return NULL;
+ if ( g_file_get_contents ("/etc/machine-id", &contents, NULL, NULL)
+ || g_file_get_contents (LOCALSTATEDIR "/lib/dbus/machine-id", &contents, NULL, NULL)) {
+ contents = g_strstrip (contents);
+ success = machine_id_parse (contents, uuid);
+ if (success) {
+ /* Hash the machine ID so it's not leaked to the network */
+ sum = g_checksum_new (G_CHECKSUM_SHA256);
+ g_checksum_update (sum, (const guchar *) &uuid, sizeof (uuid));
+ g_checksum_get_digest (sum, buffer, &sumlen);
+ g_checksum_free (sum);
+ }
+ g_free (contents);
}
- contents = g_strstrip (contents);
- success = machine_id_parse (contents, uuid);
- g_free (contents);
-
if (!success) {
- nm_log_warn (LOGD_DHCP6, "Failed to parse " SYSCONFDIR "/machine-id to generate DHCPv6 DUID.");
- return NULL;
+ nm_log_warn (LOGD_DHCP6, "Failed to read " SYSCONFDIR "/machine-id "
+ "or " LOCALSTATEDIR "/lib/dbus/machine-id to generate "
+ "DHCPv6 DUID; creating non-persistent random DUID.");
+
+ rand = g_rand_new ();
+ for (i = 0; i < sizeof (buffer) / sizeof (guint32); i++)
+ ((guint32 *) buffer)[i] = g_rand_int (rand);
+ g_rand_free (rand);
}
- /* Hash the machine ID so it's not leaked to the network */
- sum = g_checksum_new (G_CHECKSUM_SHA256);
- g_checksum_update (sum, (const guchar *) &uuid, sizeof (uuid));
- g_checksum_get_digest (sum, buffer, &sumlen);
- g_checksum_free (sum);
-
/* Generate a DHCP Unique Identifier for DHCPv6 using the
* DUID-UUID method (see RFC 6355 section 4). Format is:
*
@@ -431,10 +435,11 @@
if (G_UNLIKELY (duid == NULL)) {
duid = generate_duid_from_machine_id ();
+ g_assert (duid);
if (nm_logging_level_enabled (LOGL_DEBUG)) {
escaped = escape_duid (duid);
- nm_log_dbg (LOGD_DHCP6, "Generated DUID from machine-id: %s", escaped);
+ nm_log_dbg (LOGD_DHCP6, "Generated DUID %s", escaped);
g_free (escaped);
}
}
|