Apache HTTPD
getuuid.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * This attempts to generate V1 UUIDs according to the Internet Draft
19 * located at http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt
20 */
21#include "apr.h"
22#include "apr_uuid.h"
23#include "apr_md5.h"
24#include "apr_general.h"
25#include "apr_portable.h"
26
27
28#if APR_HAVE_UNISTD_H
29#include <unistd.h> /* for getpid, gethostname */
30#endif
31#if APR_HAVE_STDLIB_H
32#include <stdlib.h> /* for rand, srand */
33#endif
34
35
36#if APR_HAVE_STRING_H
37#include <string.h>
38#endif
39#if APR_HAVE_STRINGS_H
40#include <strings.h>
41#endif
42#if APR_HAVE_NETDB_H
43#include <netdb.h>
44#endif
45#if APR_HAVE_SYS_TIME_H
46#include <sys/time.h> /* for gettimeofday */
47#endif
48
49#define NODE_LENGTH 6
50
52static unsigned char uuid_state_node[NODE_LENGTH] = { 0 };
53
54
55static void get_random_info(unsigned char node[NODE_LENGTH])
56{
57#if APR_HAS_RANDOM
58
60
61#else
62
63 unsigned char seed[APR_MD5_DIGESTSIZE];
65
66 /* ### probably should revise some of this to be a bit more portable */
67
68 /* Leach & Salz use Linux-specific struct sysinfo;
69 * replace with pid/tid for portability (in the spirit of mod_unique_id) */
70 struct {
71 /* Add thread id here, if applicable, when we get to pthread or apr */
72 pid_t pid;
73#ifdef NETWARE
75#else
76 struct timeval t;
77#endif
78 char hostname[257];
79
80 } r;
81
83#ifdef NETWARE
84 r.pid = NXThreadGetId();
86#else
87 r.pid = getpid();
88 gettimeofday(&r.t, (struct timezone *)0);
89#endif
91 apr_md5_update(&c, (const unsigned char *)&r, sizeof(r));
92 apr_md5_final(seed, &c);
93
94 memcpy(node, seed, NODE_LENGTH); /* use a subset of the seed bytes */
95#endif
96}
97
98/* This implementation generates a random node ID instead of a
99 system-dependent call to get IEEE node ID. This is also more secure:
100 we aren't passing out our MAC address.
101*/
102static void get_pseudo_node_identifier(unsigned char *node)
103{
104 get_random_info(node);
105 node[0] |= 0x01; /* this designates a random multicast node ID */
106}
107
109{
110 /* ### fix this call to be more portable? */
112
113 /* Offset between UUID formatted times and Unix formatted times.
114 UUID UTC base time is October 15, 1582.
115 Unix base time is January 1, 1970. */
116 *uuid_time = (*uuid_time * 10) + APR_TIME_C(0x01B21DD213814000);
117}
118
119/* true_random -- generate a crypto-quality random number. */
120static int true_random(void)
121{
123
124#if APR_HAS_RANDOM
125 unsigned char buf[2];
126
128 return (buf[0] << 8) | buf[1];
129 }
130#endif
131
132 /* crap. this isn't crypto quality, but it will be Good Enough */
133
135 srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff));
136
137 return rand() & 0x0FFFF;
138}
139
145
146static void get_current_time(apr_uint64_t *timestamp)
147{
148 /* ### this needs to be made thread-safe! */
149
151 static apr_uint64_t time_last = 0;
152 static apr_uint64_t fudge = 0;
153
155
156 /* if clock reading changed since last UUID generated... */
157 if (time_last != time_now) {
158 /* The clock reading has changed since the last UUID was generated.
159 Reset the fudge factor. if we are generating them too fast, then
160 the fudge may need to be reset to something greater than zero. */
161 if (time_last + fudge > time_now)
162 fudge = time_last + fudge - time_now + 1;
163 else
164 fudge = 0;
166 }
167 else {
168 /* We generated two really fast. Bump the fudge factor. */
169 ++fudge;
170 }
171
172 *timestamp = time_now + fudge;
173}
174
176{
177 apr_uint64_t timestamp;
178 unsigned char *d = uuid->data;
179
180#if APR_HAS_OS_UUID
181 if (apr_os_uuid_get(d) == APR_SUCCESS) {
182 return;
183 }
184#endif /* !APR_HAS_OS_UUID */
185
186 if (!uuid_state_node[0])
187 init_state();
188
189 get_current_time(&timestamp);
190
191 /* time_low, uint32 */
192 d[3] = (unsigned char)timestamp;
193 d[2] = (unsigned char)(timestamp >> 8);
194 d[1] = (unsigned char)(timestamp >> 16);
195 d[0] = (unsigned char)(timestamp >> 24);
196 /* time_mid, uint16 */
197 d[5] = (unsigned char)(timestamp >> 32);
198 d[4] = (unsigned char)(timestamp >> 40);
199 /* time_hi_and_version, uint16 */
200 d[7] = (unsigned char)(timestamp >> 48);
201 d[6] = (unsigned char)(((timestamp >> 56) & 0x0F) | 0x10);
202 /* clock_seq_hi_and_reserved, uint8 */
203 d[8] = (unsigned char)(((uuid_state_seqnum >> 8) & 0x3F) | 0x80);
204 /* clock_seq_low, uint8 */
205 d[9] = (unsigned char)uuid_state_seqnum;
206 /* node, byte[6] */
208}
APR Miscellaneous library routines.
APR MD5 Routines.
APR Portability Routines.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR UUID library.
static void get_random_info(unsigned char node[6])
Definition getuuid.c:55
static unsigned char uuid_state_node[6]
Definition getuuid.c:52
APU_DECLARE(void)
Computes SipHash-2-4, producing a 64bit (APR_SIPHASH_DSIZE) hash from a message and a 128bit (APR_SIP...
Definition getuuid.c:175
#define NODE_LENGTH
Definition getuuid.c:49
static void get_current_time(apr_uint64_t *timestamp)
Definition getuuid.c:146
static int true_random(void)
Definition getuuid.c:120
static void get_system_time(apr_uint64_t *uuid_time)
Definition getuuid.c:108
static void get_pseudo_node_identifier(unsigned char *node)
Definition getuuid.c:102
static int uuid_state_seqnum
Definition getuuid.c:51
static void init_state(void)
Definition getuuid.c:140
const char * hostname
request_rec * r
const unsigned char * buf
Definition util_md5.h:50
#define APR_MD5_DIGESTSIZE
Definition apr_md5.h:68
const apr_uuid_t * uuid
Definition apr_uuid.h:62
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_interval_time_t t
#define APR_TIME_C(val)
Definition apr_time.h:49
unsigned char data[16]
Definition apr_uuid.h:42
const char * hostname
Definition httpd.h:883