#include <stdint.h>
#include <sys/time.h>
#include <stdio.h>
+#include <errno.h>
+
+#include <inttypes.h>
#include "hash.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if.h>
+#include <unistd.h>
#endif
#ifdef __APPLE__
#include <iphlpapi.h>
#endif
+#if 0
+static void pnode(uint64_t node) {
+ unsigned int bytes[6];
+ int i;
+ for (i=0;i<6;i++) {
+ bytes[5-i] = node & 0xff;
+ node >>= 8;
+ }
+
+ fprintf(stderr, "%02x", bytes[0]);
+
+ for (i=1;i<6;i++) {
+ fprintf(stderr, ":%02x", bytes[i]);
+ }
+ fprintf(stderr, "\n");
+}
+#endif
+
static void set_time_low(pd_uuid_t *u, uint32_t low) {
u->data[0] = (low >> 24) & 0xff;
u->data[1] = (low >> 16) & 0xff;
static uint64_t current_time(void) {
uint64_t now;
struct timeval tv;
+ static int seq = 0;
/* TODO is this BSD specific? */
gettimeofday(&tv, 0);
- now = (tv.tv_sec * 10000000ULL + tv.tv_usec * 10ULL) + GREGORIAN;
+ now = (tv.tv_sec * 10000000ULL + tv.tv_usec * 10ULL + seq++ % 10) + GREGORIAN;
return now;
}
return node;
}
+
/*
* TODO would probably make more sense to use a destination array
* rather than returning an integer
if (req->ifr_flags & IFF_NOARP) {
continue;
}
+
+
if (ioctl(s, SIOCGIFHWADDR, req) == 0) {
- int j;
data = (unsigned char *)req->ifr_hwaddr.sa_data;
node = data[0];
node = node << 8; node += data[1];
node = node << 8; node += data[3];
node = node << 8; node += data[4];
node = node << 8; node += data[5];
+ close(s);
+
return node;
+ } else {
+ fprintf(stderr, "ioctl to read address failed: %d\n", errno);
}
}
}
+ close(s);
}
#endif
}
static int read_state(struct pd_uuid_state *s) {
+ uint64_t node;
+
s->available = 0;
- s->node = 0LL;
- s->clock_sequence = 0;
- s->timestamp = 0LL;
+
+ node = current_node(s);
+
+ if (!s->available || s->node != node) {
+ s->clock_sequence = random_clock_sequence(s);
+ }
+ s->node = node;
return 0;
}
return i;
}
+int pd_uuid_init(struct pd_uuid_state *s, int flags) {
+ if (!s) return 0;
+
+ s->get_lock = obtain_global_lock;
+ s->release_lock = release_global_lock;
+ s->lock_data = 0;
+
+ if (flags & 0x1) {
+ s->read_state = 0;
+ s->save_state = 0;
+ s->node = current_node(s);
+ } else {
+ s->read_state = read_state;
+ s->save_state = 0;
+ }
+
+ s->random_bytes = get_bytes;
+ s->rng_state = 0;
+
+ s->available = 0;
+
+ return 1;
+}
+
int pd_uuid_init_state(struct pd_uuid_state *s) {
if (!s) return 0;
s->random_bytes = get_bytes;
s->rng_state = 0;
+ s->node = 0;
s->available = 0;
return 1;
}
+static int pd_uuid_make_v1_any(struct pd_uuid_state *s, pd_uuid_t *uuid, int rmac);
int pd_uuid_make_v1(struct pd_uuid_state *s, pd_uuid_t *uuid) {
+ return pd_uuid_make_v1_any(s, uuid, 0);
+}
+
+int pd_uuid_make_v1mc(struct pd_uuid_state *s, pd_uuid_t *uuid) {
+ return pd_uuid_make_v1_any(s, uuid, 1);
+}
+
+static int pd_uuid_make_v1_any(struct pd_uuid_state *s, pd_uuid_t *uuid, int rmac) {
struct pd_uuid_state ls;
uint64_t now;
uint64_t node;
}
now = current_time();
- node = current_node(s);
+ if (rmac) {
+ node = random_mc_mac(s);
+ } else {
+ node = current_node(s);
+ }
if (!s->available || s->node != node) {
s->clock_sequence = random_clock_sequence(s);
return 1;
}
-int pd_uuid_make_v1mc(struct pd_uuid_state *ps, pd_uuid_t *uuid) {
- struct pd_uuid_state s;
- uint64_t now;
- uint64_t node;
-
- obtain_global_lock(0);
- read_state(&s);
- now = current_time();
- node = random_mc_mac(&s);
- if (!s.available) {
- s.clock_sequence = random_clock_sequence(&s);
- }
-
- if (s.available && s.timestamp > now) {
- s.clock_sequence++;
- } else {
- s.timestamp = now;
- }
-
- save_state(&s);
- release_global_lock(0);
- s.node = node;
-
- format_uuid(uuid, &s, 1);
-
- return 1;
-}
-
int pd_uuid_make_v4(struct pd_uuid_state *s, pd_uuid_t *uuid) {
random_bytes(uuid, sizeof *uuid);
set_version(uuid, 4);
return 1;
}
+/*
+ * s must point to enough space, i.e. at least 37 bytes.
+ * this is constrained enough that sprintf could
+ * probably be avoided
+ */
+char *pd_uuid_get_string(pd_uuid_t *uuid, char *s) {
+ char *r;
+ int i;
+
+ r = s;
+
+ for (i=0;i<16;i++) {
+ r += sprintf(r, "%.2x", (int)uuid->data[i]);
+ if (i == 3 || i == 5 || i == 7 || i == 9) {
+ *r++ = '-';
+ *r = 0;
+ }
+ }
+
+ return s;
+}
+
+/*
+ * might be faster to sscanf in four bytes at a time
+ * and using htonl()
+ * A nybble loop might be faster yet.
+ */
int pd_uuid_set_string(pd_uuid_t *uuid, char *s) {
unsigned int byte;
int i;
}
return 1;
}
+
+/* pre-defined namespace uuids */
+
+pd_uuid_t pd_uuid_ns_dns = {
+ {
+ 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
+ 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
+ }
+};
+
+pd_uuid_t pd_uuid_ns_url = {
+ {
+ 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
+ 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
+ }
+};
+
+pd_uuid_t pd_uuid_ns_oid = {
+ {
+ 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
+ 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
+ }
+};
+
+pd_uuid_t pd_uuid_ns_x500 = {
+ {
+ 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
+ 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
+ }
+};
+
+int pd_uuid_copy(pd_uuid_t *src, pd_uuid_t *dst) {
+ if (src && dst) {
+ memcpy(dst->data, src->data, 16);
+ return 1;
+ }
+ return 0;
+}
+
+int pd_uuid_cmp(pd_uuid_t *a, pd_uuid_t *b) {
+ if (a && b) {
+ return memcmp(a, b, 16);
+ }
+ return 1;
+}