guid.c revision 74f436ccd2887395bd61ab6f43ce70b7b85bf2c5
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen#include "buffer.h"
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen#include "sha1.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "hash.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "hex-binary.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "hostpid.h"
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen#include "guid.h"
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <unistd.h>
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen#include <time.h>
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainenconst char *guid_generate(void)
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen{
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen static struct timespec ts = { 0, 0 };
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen static unsigned int pid = 0;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* we'll use the current time in nanoseconds as the initial 64bit
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen counter. */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (ts.tv_sec == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_fatal("clock_gettime() failed: %m");
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen pid = getpid();
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen } else if ((uint32_t)ts.tv_nsec < (uint32_t)-1) {
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen ts.tv_nsec++;
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen } else {
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen ts.tv_sec++;
9b7eeffb5752b500ac62ba1fd01c4a8c4ada14e9Timo Sirainen ts.tv_nsec = 0;
9b7eeffb5752b500ac62ba1fd01c4a8c4ada14e9Timo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen return t_strdup_printf("%04x%04lx%04x%s",
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen (unsigned int)ts.tv_nsec,
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen (unsigned long)ts.tv_sec,
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen pid, my_hostname);
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen}
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainenvoid guid_128_generate(guid_128_t guid_r)
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen static struct timespec ts = { 0, 0 };
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen static uint8_t guid_static[8];
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen unsigned char hostdomain_hash[SHA1_RESULTLEN];
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen const char *hostdomain;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen uint32_t pid;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen /* we'll use the current time in nanoseconds as the initial 64bit
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen counter. */
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen if (ts.tv_sec == 0) {
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen i_fatal("clock_gettime() failed: %m");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pid = getpid();
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen hostdomain = my_hostdomain();
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen sha1_get_digest(hostdomain, strlen(hostdomain),
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen hostdomain_hash);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen guid_static[0] = (pid & 0x000000ff);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen guid_static[1] = (pid & 0x0000ff00) >> 8;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen guid_static[2] = (pid & 0x00ff0000) >> 16;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen guid_static[3] = (pid & 0xff000000) >> 24;
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen memcpy(guid_static+4,
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen hostdomain_hash+sizeof(hostdomain_hash)-4, 4);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen } else if ((uint32_t)ts.tv_nsec < (uint32_t)-1) {
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen ts.tv_nsec++;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen } else {
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen ts.tv_sec++;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen ts.tv_nsec = 0;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen }
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen guid_r[0] = (ts.tv_nsec & 0x000000ff);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen guid_r[1] = (ts.tv_nsec & 0x0000ff00) >> 8;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen guid_r[2] = (ts.tv_nsec & 0x00ff0000) >> 16;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen guid_r[3] = (ts.tv_nsec & 0xff000000) >> 24;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen guid_r[4] = (ts.tv_sec & 0x000000ff);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen guid_r[5] = (ts.tv_sec & 0x0000ff00) >> 8;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen guid_r[6] = (ts.tv_sec & 0x00ff0000) >> 16;
683eebe490bbe5caec246c535a10ea9f93f5c330Timo Sirainen guid_r[7] = (ts.tv_sec & 0xff000000) >> 24;
683eebe490bbe5caec246c535a10ea9f93f5c330Timo Sirainen memcpy(guid_r + 8, guid_static, 8);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainenbool guid_128_is_empty(const guid_128_t guid)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen unsigned int i;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen for (i = 0; i < GUID_128_SIZE; i++) {
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen if (guid[i] != 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return TRUE;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenint guid_128_from_string(const char *str, guid_128_t guid_r)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen buffer_t buf;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen buffer_create_data(&buf, guid_r, GUID_128_SIZE);
ceb43cc04edb94445fab8f914bc4da6d740403d1Timo Sirainen return strlen(str) == GUID_128_SIZE*2 &&
ceb43cc04edb94445fab8f914bc4da6d740403d1Timo Sirainen hex_to_binary(str, &buf) == 0 &&
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen buf.used == GUID_128_SIZE ? 0 : -1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen}
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenconst char *guid_128_to_string(const guid_128_t guid)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return binary_to_hex(guid, GUID_128_SIZE);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen}
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenunsigned int guid_128_hash(const void *p)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen const uint8_t *guid = p;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return mem_hash(guid, GUID_128_SIZE);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen}
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenint guid_128_cmp(const void *p1, const void *p2)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const uint8_t *g1 = p1, *g2 = p2;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen return memcmp(g1, g2, GUID_128_SIZE);
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen}
d7e72877b7a5085c3addf9729d0bfbe1b5357853Timo Sirainen