3 * http://sourceforge.net/projects/minidlna/
5 * Much of this code and ideas for this code have been taken
6 * from Helge Deller's proposed Linux kernel patch (which
7 * apparently never made it upstream), and some from Busybox.
9 * MiniDLNA media server
10 * Copyright (C) 2009 Justin Maggard
12 * This file is part of MiniDLNA.
14 * MiniDLNA is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
18 * MiniDLNA is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
31 #include <sys/syscall.h>
34 #include <sys/ioctl.h>
38 #include "getifaddr.h"
42 #define NSEC_PER_SEC 1000000000L
43 #define NSEC_PER_MSEC 1000000L
45 static u_int32_t clock_seq
;
46 static const u_int32_t clock_seq_max
= 0x3fff; /* 14 bits */
47 static int clock_seq_initialized
;
54 syscall(__NR_clock_gettime
, CLOCK_MONOTONIC
, &ts
);
55 return ts
.tv_sec
* 1000000ULL + ts
.tv_nsec
/ 1000;
59 read_bootid_node(unsigned char *buf
, size_t size
)
66 boot_id
= fopen("/proc/sys/kernel/random/boot_id", "r");
69 if((fseek(boot_id
, 24, SEEK_SET
) < 0) ||
70 (fscanf(boot_id
, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
71 &buf
[0], &buf
[1], &buf
[2], &buf
[3], &buf
[4], &buf
[5]) != 6))
82 read_random_bytes(unsigned char *buf
, size_t size
)
87 i
= open("/dev/urandom", O_RDONLY
);
93 /* Paranoia. /dev/urandom may be missing.
94 * rand() is guaranteed to generate at least [0, 2^15) range,
95 * but lowest bits in some libc are not so "random". */
96 srand(monotonic_us());
100 for(i
= 0; i
< size
; i
++)
101 buf
[i
] ^= rand() >> 5;
112 unsigned char buf
[4];
114 read_random_bytes(buf
, 4);
115 memcpy(&clock_seq
, &buf
, sizeof(clock_seq
));
116 clock_seq
&= clock_seq_max
;
117 clock_seq_initialized
= 1;
121 generate_uuid(unsigned char uuid_out
[16])
123 static u_int64_t last_time_all
;
124 static unsigned int clock_seq_started
;
125 static char last_node
[6] = { 0, 0, 0, 0, 0, 0 };
129 int inc_clock_seq
= 0;
131 unsigned char mac
[6];
134 memset(&mac
, '\0', sizeof(mac
));
135 /* Get the spatially unique node identifier */
137 mac_error
= getsyshwaddr((char *)mac
, sizeof(mac
));
141 memcpy(&uuid_out
[10], mac
, ETH_ALEN
);
145 /* use bootid's nodeID if no network interface found */
146 DPRINTF(E_INFO
, L_HTTP
, "Could not find MAC. Use bootid's nodeID.\n");
147 if( read_bootid_node(&uuid_out
[10], 6) != 0)
149 DPRINTF(E_INFO
, L_HTTP
, "bootid node not successfully read.\n");
150 read_random_bytes(&uuid_out
[10], 6);
154 if(memcmp(last_node
, uuid_out
+10, 6) != 0)
157 memcpy(last_node
, uuid_out
+10, 6);
160 /* Determine 60-bit timestamp value. For UUID version 1, this is
161 * represented by Coordinated Universal Time (UTC) as a count of 100-
162 * nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
163 * Gregorian reform to the Christian calendar).
165 syscall(__NR_clock_gettime
, CLOCK_REALTIME
, &ts
);
166 time_all
= ((u_int64_t
)ts
.tv_sec
) * (NSEC_PER_SEC
/ 100);
167 time_all
+= ts
.tv_nsec
/ 100;
169 /* add offset from Gregorian Calendar to Jan 1 1970 */
170 time_all
+= 12219292800000ULL * (NSEC_PER_MSEC
/ 100);
171 time_all
&= 0x0fffffffffffffffULL
; /* limit to 60 bits */
173 /* Determine clock sequence (max. 14 bit) */
174 if(!clock_seq_initialized
)
177 clock_seq_started
= clock_seq
;
181 if(inc_clock_seq
|| time_all
<= last_time_all
)
183 clock_seq
= (clock_seq
+ 1) & clock_seq_max
;
184 if(clock_seq
== clock_seq_started
)
186 clock_seq
= (clock_seq
- 1) & clock_seq_max
;
190 clock_seq_started
= clock_seq
;
192 last_time_all
= time_all
;
194 /* Fill in timestamp and clock_seq values */
195 uuid_out
[3] = (u_int8_t
)time_all
;
196 uuid_out
[2] = (u_int8_t
)(time_all
>> 8);
197 uuid_out
[1] = (u_int8_t
)(time_all
>> 16);
198 uuid_out
[0] = (u_int8_t
)(time_all
>> 24);
199 uuid_out
[5] = (u_int8_t
)(time_all
>> 32);
200 uuid_out
[4] = (u_int8_t
)(time_all
>> 40);
201 uuid_out
[7] = (u_int8_t
)(time_all
>> 48);
202 uuid_out
[6] = (u_int8_t
)(time_all
>> 56);
204 uuid_out
[8] = clock_seq
>> 8;
205 uuid_out
[9] = clock_seq
& 0xff;
207 /* Set UUID version to 1 --- time-based generation */
208 uuid_out
[6] = (uuid_out
[6] & 0x0F) | 0x10;
209 /* Set the UUID variant to DCE */
210 uuid_out
[8] = (uuid_out
[8] & 0x3F) | 0x80;
215 /* Places a null-terminated 37-byte time-based UUID string in the buffer pointer to by buf.
216 * A large enough buffer must already be allocated. */
218 get_uuid_string(char *buf
)
220 unsigned char uuid
[16];
222 if( generate_uuid(uuid
) != 0 )
225 sprintf(buf
, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
226 uuid
[0], uuid
[1], uuid
[2], uuid
[3], uuid
[4], uuid
[5], uuid
[6], uuid
[7], uuid
[8],
227 uuid
[9], uuid
[10], uuid
[11], uuid
[12], uuid
[13], uuid
[14], uuid
[15]);