00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef WIN32
00037
00038
00039
00040
00041
00042 #define _SVID_SOURCE
00043
00044 #ifdef HAVE_UNISTD_H
00045 #include <unistd.h>
00046 #endif
00047 #ifdef HAVE_STDLIB_H
00048 #include <stdlib.h>
00049 #endif
00050 #include <string.h>
00051 #include <fcntl.h>
00052 #include <errno.h>
00053 #include <sys/types.h>
00054 #include <sys/time.h>
00055 #include <sys/stat.h>
00056 #include <sys/file.h>
00057 #ifdef HAVE_SYS_IOCTL_H
00058 #include <sys/ioctl.h>
00059 #endif
00060 #ifdef HAVE_SYS_SOCKET_H
00061 #include <sys/socket.h>
00062 #endif
00063 #ifdef HAVE_SYS_SOCKIO_H
00064 #include <sys/sockio.h>
00065 #endif
00066 #ifdef HAVE_NET_IF_H
00067 #include <net/if.h>
00068 #endif
00069 #ifdef HAVE_NETINET_IN_H
00070 #include <netinet/in.h>
00071 #endif
00072 #ifdef HAVE_NET_IF_DL_H
00073 #include <net/if_dl.h>
00074 #endif
00075
00076 #include "uuidP.h"
00077
00078 #ifdef HAVE_SRANDOM
00079 #define srand(x) srandom(x)
00080 #define rand() random()
00081 #endif
00082
00083 static int get_random_fd(void)
00084 {
00085 struct timeval tv;
00086 static int fd = -2;
00087 int i;
00088
00089 if (fd == -2) {
00090 gettimeofday(&tv, 0);
00091 fd = open("/dev/urandom", O_RDONLY);
00092 if (fd == -1)
00093 fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
00094 srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
00095 }
00096
00097 gettimeofday(&tv, 0);
00098 for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
00099 rand();
00100 return fd;
00101 }
00102
00103
00104
00105
00106
00107
00108 static void get_random_bytes(void *buf, int nbytes)
00109 {
00110 int i, n = nbytes, fd = get_random_fd();
00111 int lose_counter = 0;
00112 unsigned char *cp = (unsigned char *) buf;
00113
00114 if (fd >= 0) {
00115 while (n > 0) {
00116 i = read(fd, cp, n);
00117 if (i <= 0) {
00118 if (lose_counter++ > 16)
00119 break;
00120 continue;
00121 }
00122 n -= i;
00123 cp += i;
00124 lose_counter = 0;
00125 }
00126 }
00127
00128
00129
00130
00131
00132 for (cp = buf, i = 0; i < nbytes; i++)
00133 *cp++ ^= (rand() >> 7) & 0xFF;
00134 return;
00135 }
00136
00137
00138
00139
00140 static int get_node_id(unsigned char *node_id)
00141 {
00142 #ifdef HAVE_NET_IF_H
00143 int sd;
00144 struct ifreq ifr, *ifrp;
00145 struct ifconf ifc;
00146 char buf[1024];
00147 int n, i;
00148 unsigned char *a;
00149 #ifdef HAVE_NET_IF_DL_H
00150 struct sockaddr_dl *sdlp;
00151 #endif
00152
00153
00154
00155
00156
00157
00158
00159 #ifdef HAVE_SA_LEN
00160 #ifndef max
00161 #define max(a,b) ((a) > (b) ? (a) : (b))
00162 #endif
00163 #define ifreq_size(i) max(sizeof(struct ifreq),\
00164 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
00165 #else
00166 #define ifreq_size(i) sizeof(struct ifreq)
00167 #endif
00168
00169 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
00170 if (sd < 0) {
00171 return -1;
00172 }
00173 memset(buf, 0, sizeof(buf));
00174 ifc.ifc_len = sizeof(buf);
00175 ifc.ifc_buf = buf;
00176 if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
00177 close(sd);
00178 return -1;
00179 }
00180 n = ifc.ifc_len;
00181 for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
00182 ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
00183 strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
00184 #ifdef SIOCGIFHWADDR
00185 if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
00186 continue;
00187 a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
00188 #else
00189 #ifdef SIOCGENADDR
00190 if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
00191 continue;
00192 a = (unsigned char *) ifr.ifr_enaddr;
00193 #else
00194 #ifdef HAVE_NET_IF_DL_H
00195 sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
00196 if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
00197 continue;
00198 a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
00199 #else
00200
00201
00202
00203
00204 close(sd);
00205 return 0;
00206 #endif
00207 #endif
00208 #endif
00209 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
00210 continue;
00211 if (node_id) {
00212 memcpy(node_id, a, 6);
00213 close(sd);
00214 return 1;
00215 }
00216 }
00217 close(sd);
00218 #endif
00219 return 0;
00220 }
00221
00222
00223 #define MAX_ADJUSTMENT 10
00224
00225 static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq)
00226 {
00227 static int adjustment = 0;
00228 static struct timeval last = {0, 0};
00229 static uint16_t clock_seq;
00230 struct timeval tv;
00231 unsigned long long clock_reg;
00232
00233 try_again:
00234 gettimeofday(&tv, 0);
00235 if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
00236 get_random_bytes(&clock_seq, sizeof(clock_seq));
00237 clock_seq &= 0x3FFF;
00238 last = tv;
00239 last.tv_sec--;
00240 }
00241 if ((tv.tv_sec < last.tv_sec) ||
00242 ((tv.tv_sec == last.tv_sec) &&
00243 (tv.tv_usec < last.tv_usec))) {
00244 clock_seq = (clock_seq+1) & 0x3FFF;
00245 adjustment = 0;
00246 last = tv;
00247 } else if ((tv.tv_sec == last.tv_sec) &&
00248 (tv.tv_usec == last.tv_usec)) {
00249 if (adjustment >= MAX_ADJUSTMENT)
00250 goto try_again;
00251 adjustment++;
00252 } else {
00253 adjustment = 0;
00254 last = tv;
00255 }
00256
00257 clock_reg = tv.tv_usec*10 + adjustment;
00258 clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
00259 clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
00260
00261 *clock_high = clock_reg >> 32;
00262 *clock_low = clock_reg;
00263 *ret_clock_seq = clock_seq;
00264 return 0;
00265 }
00266
00267 void uuid_generate_time(uuid_t out)
00268 {
00269 static unsigned char node_id[6];
00270 static int has_init = 0;
00271 struct uuid uu;
00272 uint32_t clock_mid;
00273
00274 if (!has_init) {
00275 if (get_node_id(node_id) <= 0) {
00276 get_random_bytes(node_id, 6);
00277
00278
00279
00280
00281
00282 node_id[0] |= 0x01;
00283 }
00284 has_init = 1;
00285 }
00286 get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
00287 uu.clock_seq |= 0x8000;
00288 uu.time_mid = (uint16_t) clock_mid;
00289 uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
00290 memcpy(uu.node, node_id, 6);
00291 uuid_pack(&uu, out);
00292 }
00293
00294 void uuid_generate_random(uuid_t out)
00295 {
00296 uuid_t buf;
00297 struct uuid uu;
00298
00299 get_random_bytes(buf, sizeof(buf));
00300 uuid_unpack(buf, &uu);
00301
00302 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
00303 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
00304 uuid_pack(&uu, out);
00305 }
00306
00307
00308
00309
00310
00311
00312
00313 void uuid_generate(uuid_t out)
00314 {
00315 if (get_random_fd() >= 0)
00316 uuid_generate_random(out);
00317 else
00318 uuid_generate_time(out);
00319 }
00320
00321 #endif