2 This file is part of systemd.
4 Copyright 2011 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "hexdecoct.h"
30 #include "random-util.h"
33 _public_
char *sd_id128_to_string(sd_id128_t id
, char s
[SD_ID128_STRING_MAX
]) {
36 assert_return(s
, NULL
);
38 for (n
= 0; n
< 16; n
++) {
39 s
[n
*2] = hexchar(id
.bytes
[n
] >> 4);
40 s
[n
*2+1] = hexchar(id
.bytes
[n
] & 0xF);
48 _public_
int sd_id128_from_string(const char s
[], sd_id128_t
*ret
) {
53 assert_return(s
, -EINVAL
);
54 assert_return(ret
, -EINVAL
);
56 for (n
= 0, i
= 0; n
< 16;) {
60 /* Is this a GUID? Then be nice, and skip over
65 else if (i
== 13 || i
== 18 || i
== 23) {
75 a
= unhexchar(s
[i
++]);
79 b
= unhexchar(s
[i
++]);
83 t
.bytes
[n
++] = (a
<< 4) | b
;
86 if (i
!= (is_guid
? 36 : 32))
96 static sd_id128_t
make_v4_uuid(sd_id128_t id
) {
97 /* Stolen from generate_random_uuid() of drivers/char/random.c
98 * in the kernel sources */
100 /* Set UUID version to 4 --- truly random generation */
101 id
.bytes
[6] = (id
.bytes
[6] & 0x0F) | 0x40;
103 /* Set the UUID variant to DCE */
104 id
.bytes
[8] = (id
.bytes
[8] & 0x3F) | 0x80;
109 _public_
int sd_id128_get_machine(sd_id128_t
*ret
) {
110 static thread_local sd_id128_t saved_machine_id
;
111 static thread_local
bool saved_machine_id_valid
= false;
112 _cleanup_close_
int fd
= -1;
118 assert_return(ret
, -EINVAL
);
120 if (saved_machine_id_valid
) {
121 *ret
= saved_machine_id
;
125 fd
= open("/etc/machine-id", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
129 r
= loop_read_exact(fd
, buf
, 33, false);
135 for (j
= 0; j
< 16; j
++) {
138 a
= unhexchar(buf
[j
*2]);
139 b
= unhexchar(buf
[j
*2+1]);
144 t
.bytes
[j
] = a
<< 4 | b
;
147 saved_machine_id
= t
;
148 saved_machine_id_valid
= true;
154 _public_
int sd_id128_get_boot(sd_id128_t
*ret
) {
155 static thread_local sd_id128_t saved_boot_id
;
156 static thread_local
bool saved_boot_id_valid
= false;
157 _cleanup_close_
int fd
= -1;
164 assert_return(ret
, -EINVAL
);
166 if (saved_boot_id_valid
) {
167 *ret
= saved_boot_id
;
171 fd
= open("/proc/sys/kernel/random/boot_id", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
175 r
= loop_read_exact(fd
, buf
, 36, false);
179 for (j
= 0, p
= buf
; j
< 16; j
++) {
197 t
.bytes
[j
] = a
<< 4 | b
;
203 saved_boot_id_valid
= true;
209 _public_
int sd_id128_randomize(sd_id128_t
*ret
) {
213 assert_return(ret
, -EINVAL
);
215 r
= dev_urandom(&t
, sizeof(t
));
219 /* Turn this into a valid v4 UUID, to be nice. Note that we
220 * only guarantee this for newly generated UUIDs, not for
221 * pre-existing ones. */
223 *ret
= make_v4_uuid(t
);