guid.c revision af49da69a12b5383b89c7b2fa574c2a85b9ca310
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2011-2013 Dovecot authors, see the included COPYING file */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "lib.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "buffer.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "sha1.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "hash.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "hex-binary.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "hostpid.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "guid.h"
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include <unistd.h>
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include <time.h>
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenconst char *guid_generate(void)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen static struct timespec ts = { 0, 0 };
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen static unsigned int pid = 0;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* we'll use the current time in nanoseconds as the initial 64bit
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen counter. */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (ts.tv_sec == 0) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen i_fatal("clock_gettime() failed: %m");
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen pid = getpid();
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen } else if ((uint32_t)ts.tv_nsec < (uint32_t)-1) {
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen ts.tv_nsec++;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen } else {
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen ts.tv_sec++;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen ts.tv_nsec = 0;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return t_strdup_printf("%04x%04lx%04x%s",
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen (unsigned int)ts.tv_nsec,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen (unsigned long)ts.tv_sec,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen pid, my_hostname);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenvoid guid_128_host_hash_get(const char *host,
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen unsigned char hash_r[GUID_128_HOST_HASH_SIZE])
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen unsigned char full_hash[SHA1_RESULTLEN];
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen sha1_get_digest(host, strlen(host), full_hash);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen memcpy(hash_r, full_hash + sizeof(full_hash)-GUID_128_HOST_HASH_SIZE,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen GUID_128_HOST_HASH_SIZE);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenvoid guid_128_generate(guid_128_t guid_r)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#if GUID_128_HOST_HASH_SIZE != 4
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen# error GUID_128_HOST_HASH_SIZE must be 4
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#endif
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen static struct timespec ts = { 0, 0 };
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen static uint8_t guid_static[8];
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen uint32_t pid;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* we'll use the current time in nanoseconds as the initial 64bit
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen counter. */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (ts.tv_sec == 0) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen i_fatal("clock_gettime() failed: %m");
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen pid = getpid();
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_static[0] = (pid & 0x000000ff);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_static[1] = (pid & 0x0000ff00) >> 8;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_static[2] = (pid & 0x00ff0000) >> 16;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_static[3] = (pid & 0xff000000) >> 24;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_128_host_hash_get(my_hostdomain(), guid_static+4);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen } else if ((uint32_t)ts.tv_nsec < (uint32_t)-1) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen ts.tv_nsec++;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen } else {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen ts.tv_sec++;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen ts.tv_nsec = 0;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_r[0] = (ts.tv_nsec & 0x000000ff);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_r[1] = (ts.tv_nsec & 0x0000ff00) >> 8;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_r[2] = (ts.tv_nsec & 0x00ff0000) >> 16;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_r[3] = (ts.tv_nsec & 0xff000000) >> 24;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_r[4] = (ts.tv_sec & 0x000000ff);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_r[5] = (ts.tv_sec & 0x0000ff00) >> 8;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_r[6] = (ts.tv_sec & 0x00ff0000) >> 16;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen guid_r[7] = (ts.tv_sec & 0xff000000) >> 24;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen memcpy(guid_r + 8, guid_static, 8);
956b8eea7ae479a38b25175447fc8eac2df30480Timo Sirainen}
956b8eea7ae479a38b25175447fc8eac2df30480Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenbool guid_128_is_empty(const guid_128_t guid)
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen{
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen unsigned int i;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen for (i = 0; i < GUID_128_SIZE; i++) {
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen if (guid[i] != 0)
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen return FALSE;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return TRUE;
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen}
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainenint guid_128_from_string(const char *str, guid_128_t guid_r)
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen{
ecd14e4323bfe9953db9be89dc75858592018a75Timo Sirainen buffer_t buf;
ecd14e4323bfe9953db9be89dc75858592018a75Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen buffer_create_from_data(&buf, guid_r, GUID_128_SIZE);
b91b14dfb49823ffa445aa50c56d23c67b888cd4Timo Sirainen return strlen(str) == GUID_128_SIZE*2 &&
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen hex_to_binary(str, &buf) == 0 &&
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen buf.used == GUID_128_SIZE ? 0 : -1;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen}
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainen
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainenconst char *guid_128_to_string(const guid_128_t guid)
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainen{
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen return binary_to_hex(guid, GUID_128_SIZE);
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen}
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainenunsigned int guid_128_hash(const uint8_t *guid)
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return mem_hash(guid, GUID_128_SIZE);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenint guid_128_cmp(const uint8_t *guid1, const uint8_t *guid2)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return memcmp(guid1, guid2, GUID_128_SIZE);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen