]>
Commit | Line | Data |
---|---|---|
d8feb2d7 SS |
1 | diff -up dhcp-4.3.4/client/dhclient.c.duid_uuid dhcp-4.3.4/client/dhclient.c |
2 | --- dhcp-4.3.4/client/dhclient.c.duid_uuid 2016-04-29 12:58:14.846150838 +0200 | |
3 | +++ dhcp-4.3.4/client/dhclient.c 2016-04-29 12:58:14.851150839 +0200 | |
4 | @@ -3868,6 +3868,59 @@ write_options(struct client_state *clien | |
5 | } | |
6 | } | |
7 | ||
8 | +int unhexchar(char c) { | |
9 | + | |
10 | + if (c >= '0' && c <= '9') | |
11 | + return c - '0'; | |
12 | + | |
13 | + if (c >= 'a' && c <= 'f') | |
14 | + return c - 'a' + 10; | |
15 | + | |
16 | + if (c >= 'A' && c <= 'F') | |
17 | + return c - 'A' + 10; | |
18 | + | |
19 | + return -1; | |
20 | +} | |
21 | + | |
22 | +isc_result_t | |
23 | +read_uuid(u_int8_t* uuid) { | |
24 | + const char *id_fname = "/etc/machine-id"; | |
25 | + char id[32]; | |
26 | + size_t nread; | |
27 | + FILE * file = fopen( id_fname , "r"); | |
28 | + if (!file) { | |
29 | + log_debug("Cannot open %s", id_fname); | |
30 | + return ISC_R_IOERROR; | |
31 | + } | |
32 | + nread = fread(id, 1, sizeof id, file); | |
33 | + fclose(file); | |
34 | + | |
35 | + if (nread < 32) { | |
36 | + log_debug("Not enough data in %s", id_fname); | |
37 | + return ISC_R_IOERROR; | |
38 | + } | |
39 | + | |
40 | + for (int j = 0; j < 16; j++) { | |
41 | + int a, b; | |
42 | + | |
43 | + a = unhexchar(id[j*2]); | |
44 | + b = unhexchar(id[j*2+1]); | |
45 | + | |
46 | + if (a < 0 || b < 0) { | |
47 | + log_debug("Wrong data in %s", id_fname); | |
48 | + return ISC_R_IOERROR; | |
49 | + } | |
50 | + uuid[j] = a << 4 | b; | |
51 | + } | |
52 | + | |
53 | + /* Set UUID version to 4 --- truly random generation */ | |
54 | + uuid[6] = (uuid[6] & 0x0F) | 0x40; | |
55 | + /* Set the UUID variant to DCE */ | |
56 | + uuid[8] = (uuid[8] & 0x3F) | 0x80; | |
57 | + | |
58 | + return ISC_R_SUCCESS; | |
59 | +} | |
60 | + | |
61 | /* | |
62 | * The "best" default DUID, since we cannot predict any information | |
63 | * about the system (such as whether or not the hardware addresses are | |
64 | @@ -3888,6 +3941,7 @@ form_duid(struct data_string *duid, cons | |
65 | struct interface_info *ip; | |
66 | int len; | |
67 | char *str; | |
68 | + u_int8_t uuid[16]; | |
69 | ||
70 | /* For now, just use the first interface on the list. */ | |
71 | ip = interfaces; | |
72 | @@ -3908,9 +3962,16 @@ form_duid(struct data_string *duid, cons | |
73 | (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf))) | |
74 | log_fatal("Impossible hardware address length at %s:%d.", MDL); | |
75 | ||
76 | - if (duid_type == 0) | |
77 | - duid_type = stateless ? DUID_LL : DUID_LLT; | |
78 | - | |
79 | + if (duid_type == 0) { | |
80 | + if (read_uuid(uuid) == ISC_R_SUCCESS) | |
81 | + duid_type = DUID_UUID; | |
82 | + else | |
83 | + duid_type = stateless ? DUID_LL : DUID_LLT; | |
84 | + } | |
85 | + | |
86 | + if (duid_type == DUID_UUID) | |
87 | + len = 2 + sizeof (uuid); | |
88 | + else { | |
89 | /* | |
90 | * 2 bytes for the 'duid type' field. | |
91 | * 2 bytes for the 'htype' field. | |
92 | @@ -3921,13 +3982,18 @@ form_duid(struct data_string *duid, cons | |
93 | len = 4 + (ip->hw_address.hlen - 1); | |
94 | if (duid_type == DUID_LLT) | |
95 | len += 4; | |
96 | + } | |
97 | if (!buffer_allocate(&duid->buffer, len, MDL)) | |
98 | log_fatal("no memory for default DUID!"); | |
99 | duid->data = duid->buffer->data; | |
100 | duid->len = len; | |
101 | ||
102 | + if (duid_type == DUID_UUID) { | |
103 | + putUShort(duid->buffer->data, DUID_UUID); | |
104 | + memcpy(duid->buffer->data + 2, uuid, sizeof(uuid)); | |
105 | + } | |
106 | /* Basic Link Local Address type of DUID. */ | |
107 | - if (duid_type == DUID_LLT) { | |
108 | + else if (duid_type == DUID_LLT) { | |
109 | putUShort(duid->buffer->data, DUID_LLT); | |
110 | putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]); | |
111 | putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH); |