uuid.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* uuid.c */
  13. /*
  14. ** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
  15. ** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
  16. ** Digital Equipment Corporation, Maynard, Mass.
  17. ** Copyright (c) 1998 Microsoft.
  18. ** To anyone who acknowledges that this file is provided "AS IS"
  19. ** without any express or implied warranty: permission to use, copy,
  20. ** modify, and distribute this file for any purpose is hereby
  21. ** granted without fee, provided that the above copyright notices and
  22. ** this notice appears in all source code copies, and that none of
  23. ** the names of Open Software Foundation, Inc., Hewlett-Packard
  24. ** Company, or Digital Equipment Corporation be used in advertising
  25. ** or publicity pertaining to distribution of the software without
  26. ** specific, written prior permission. Neither Open Software
  27. ** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital Equipment
  28. * Corporation makes any representations about the suitability of
  29. ** this software for any purpose.
  30. */
  31. #include <string.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <time.h>
  35. #include <pk11func.h>
  36. #include <sys/types.h>
  37. #include <sys/time.h>
  38. #include <sys/sysinfo.h>
  39. #include <sys/utsname.h>
  40. #include <unistd.h> /* gethostname() */
  41. #include "slap.h"
  42. #include "uuid.h"
  43. #include "sechash.h"
  44. #define SEQ_PER_SEC 10000000 /* number of 100ns intervals in a sec */
  45. #define STATE_FILE "state" /* file that contains generator's state */
  46. #define STATE_ATTR "nsState" /* attribute that stores state info */
  47. #define MODULE "uuid" /* for logging */
  48. #define UPDATE_INTERVAL 60000 /* 1 minute */
  49. #define NEED_TIME_UPDATE -1
  50. #define SEED_LENGTH 16
  51. /* generates uuid in singlethreaded environment */
  52. static int uuid_create_st(guid_t *uuid);
  53. /* generates uuid in multithreaded environment */
  54. static int uuid_create_mt(guid_t *uuid);
  55. /* periodically called to update generator's state - mt case only */
  56. static void uuid_update_state (time_t when, void *arg);
  57. /* creates uuid in v1 format using current state info */
  58. static void format_uuid_v1(guid_t *uuid, uuid_time_t timestamp, unsigned16 clock_seq);
  59. /* generates uuid in v3 format */
  60. static void format_uuid_v3(guid_t *uuid, unsigned char hash[16]);
  61. /* reads state from a file or DIT entry */
  62. static int read_state (const char *configDir, const Slapi_DN *configDN, PRBool *newState);
  63. /* reads state from a file */
  64. static int read_state_from_file (const char *configDir);
  65. /* read state information from DIT */
  66. static int read_state_from_entry (const Slapi_DN *configDN);
  67. /* writes state to persistent store: file or dit */
  68. static int write_state(PRBool newState);
  69. /* writes state to a file */
  70. static int write_state_to_file();
  71. /* writes state to dit */
  72. static int write_state_to_entry(PRBool newState);
  73. /* add state entry to the dit */
  74. static int add_state_entry ();
  75. /* modify state entry in the dit */
  76. static int modify_state_entry ();
  77. /* generates timestamp for the next uuid - single threaded */
  78. static uuid_time_t update_time();
  79. /* generates timestamp for the next uuid - multithreaded threaded */
  80. static int update_time_mt(uuid_time_t *timestamp, unsigned16 *clock_seq);
  81. /* retrieves or generates nodeid */
  82. static int get_node_identifier(uuid_node_t *node);
  83. /* returns current time in the UTC format */
  84. static void get_system_time(uuid_time_t *uuid_time);
  85. /* generates random value - used to set clock sequence */
  86. static unsigned16 true_random(void);
  87. /* generate random info buffer to generate nodeid */
  88. static void get_random_info(unsigned char seed[], size_t arraylen);
  89. /* UUID generator state stored persistently */
  90. typedef struct
  91. {
  92. uuid_time_t timestamp; /* saved timestamp */
  93. uuid_node_t node; /* saved node ID */
  94. unsigned16 clockseq; /* saved clock sequence */
  95. unsigned8 last_update;/* flags the update made during server sutdown */
  96. } uuid_gen_state;
  97. /* generator state plus data to support it */
  98. typedef struct
  99. {
  100. uuid_gen_state genstate; /* generator state */
  101. int time_seq; /* sequence number to account for clock
  102. granularity; not written to disk */
  103. PRBool initialized; /* uniqueid successfully initialized */
  104. PRBool mtGen; /* multithreaded generation */
  105. PRLock *lock; /* lock to protect state */
  106. PRFileDesc *fd; /* fd for the state file */
  107. Slapi_DN *configDN; /* db entry that contains state info */
  108. } uuid_state;
  109. static unsigned int uuid_seed = 0; /* seed for the random generator */
  110. uuid_state _state; /* generator's state */
  111. /* uuid_init -- initializes uuid layer */
  112. int uuid_init (const char *configDir, const Slapi_DN *configDN, PRBool mtGen)
  113. {
  114. int rt;
  115. PRBool newState = PR_FALSE;
  116. if (_state.initialized)
  117. {
  118. slapi_log_error (SLAPI_LOG_FATAL, MODULE,
  119. "uuid_init: generator is already initialized\n");
  120. return UUID_SUCCESS;
  121. }
  122. memset (&_state, 0, sizeof (_state));
  123. /* get saved state */
  124. rt = read_state(configDir, configDN, &newState);
  125. if (rt != UUID_SUCCESS)
  126. {
  127. slapi_log_error (SLAPI_LOG_FATAL, MODULE,
  128. "uuid_init: failed to get generator's state\n");
  129. uuid_cleanup ();
  130. return rt;
  131. }
  132. _state.mtGen = mtGen;
  133. /* this is multithreaded generation - create lock */
  134. if (_state.mtGen)
  135. {
  136. _state.lock = PR_NewLock();
  137. if (!_state.lock)
  138. {
  139. PRErrorCode prerr = PR_GetError();
  140. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uuid_init: "
  141. "failed to create state lock; " SLAPI_COMPONENT_NAME_NSPR " error %d (%s).\n",
  142. prerr, slapd_pr_strerror(prerr));
  143. uuid_cleanup ();
  144. return UUID_LOCK_ERROR;
  145. }
  146. }
  147. /* save the state */
  148. rt = write_state(newState);
  149. /* can't proceede if the state can't be written */
  150. if (rt != UUID_SUCCESS)
  151. {
  152. if (slapi_config_get_readonly() &&
  153. (rt == UUID_LDAP_ERROR)) {
  154. /*
  155. * If server is readonly and error is UUID_LDAP_ERROR
  156. * we can continue.
  157. */
  158. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "Warning: "
  159. "The server is in read-only mode, therefore the unique ID generator cannot be used. "
  160. "Do not use this server in any replication agreement\n");
  161. }
  162. else {
  163. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uuid_init: "
  164. "failed to save generator's state.\n");
  165. uuid_cleanup ();
  166. return rt;
  167. }
  168. }
  169. /* schedule update task for multithreaded generation */
  170. if (_state.mtGen)
  171. slapi_eq_repeat(uuid_update_state, NULL, (time_t)0, UPDATE_INTERVAL);
  172. _state.initialized = PR_TRUE;
  173. return UUID_SUCCESS;
  174. }
  175. /* uuid_cleanup -- saves state, destroys generator data */
  176. void uuid_cleanup ()
  177. {
  178. if (_state.initialized)
  179. {
  180. _state.genstate.last_update = 1;
  181. write_state (PR_FALSE);
  182. }
  183. if (_state.lock)
  184. PR_DestroyLock (_state.lock);
  185. if (_state.fd)
  186. PR_Close (_state.fd);
  187. if (_state.configDN)
  188. slapi_sdn_free(&_state.configDN);
  189. memset (&_state, 0, sizeof (_state));
  190. }
  191. /* uuid_create - main generating function */
  192. int uuid_create(guid_t *uuid)
  193. {
  194. if (_state.mtGen)
  195. return uuid_create_mt(uuid);
  196. else
  197. return uuid_create_st(uuid);
  198. }
  199. /* uuid_compare -- Compare two UUID's "lexically" and return
  200. -1 u1 is lexically before u2
  201. 0 u1 is equal to u2
  202. 1 u1 is lexically after u2
  203. Note: lexical ordering is not temporal ordering!
  204. */
  205. #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
  206. int uuid_compare(const guid_t *u1, const guid_t *u2)
  207. {
  208. int i;
  209. CHECK(u1->time_low, u2->time_low);
  210. CHECK(u1->time_mid, u2->time_mid);
  211. CHECK(u1->time_hi_and_version, u2->time_hi_and_version);
  212. CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved);
  213. CHECK(u1->clock_seq_low, u2->clock_seq_low)
  214. for (i = 0; i < 6; i++)
  215. {
  216. if (u1->node[i] < u2->node[i])
  217. return -1;
  218. if (u1->node[i] > u2->node[i])
  219. return 1;
  220. }
  221. return 0;
  222. }
  223. /* uuid_format -- converts UUID to its string representation
  224. buffer should be at list 40 bytes long
  225. */
  226. void uuid_format(const guid_t *u, char *buff)
  227. {
  228. sprintf(buff, "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
  229. (unsigned int)u->time_low, u->time_mid, u->time_hi_and_version,
  230. u->clock_seq_hi_and_reserved, u->clock_seq_low, u->node[0],
  231. u->node[1], u->node[2], u->node[3], u->node[4], u->node[5]);
  232. }
  233. /* uuid_create_from_name -- create a UUID using a "name" from a "name space"
  234. */
  235. void uuid_create_from_name(guid_t * uuid, /* resulting UUID */
  236. const guid_t nsid, /* UUID to serve as context, so identical
  237. names from different name spaces generate
  238. different UUIDs */
  239. const void * name, /* the name from which to generate a UUID */
  240. int namelen) /* the length of the name */
  241. {
  242. PK11Context *c = NULL;
  243. unsigned char hash[16];
  244. unsigned int hashLen;
  245. guid_t net_nsid; /* context UUID in network byte order */
  246. memset(hash, 0, 16);
  247. /* put name space ID in network byte order so it hashes the same
  248. no matter what endian machine we're on */
  249. memset(&net_nsid, 0, sizeof(guid_t));
  250. net_nsid.time_low = PR_htonl(nsid.time_low);
  251. net_nsid.time_mid = PR_htons(nsid.time_mid);
  252. net_nsid.time_hi_and_version = PR_htons(nsid.time_hi_and_version);
  253. net_nsid.clock_seq_hi_and_reserved=nsid.clock_seq_hi_and_reserved;
  254. net_nsid.clock_seq_low=nsid.clock_seq_low;
  255. strncpy((char *)net_nsid.node, (char *)nsid.node, 6);
  256. c = PK11_CreateDigestContext(SEC_OID_MD5);
  257. if (c != NULL) {
  258. PK11_DigestBegin(c);
  259. PK11_DigestOp(c, (unsigned char *)&net_nsid, sizeof(net_nsid));
  260. PK11_DigestOp(c, (unsigned char *)name, namelen);
  261. PK11_DigestFinal(c, hash, &hashLen, 16);
  262. /* the hash is in network byte order at this point */
  263. format_uuid_v3(uuid, hash);
  264. PK11_DestroyContext(c, PR_TRUE);
  265. }
  266. else { /* Probably desesperate but at least deterministic... */
  267. memset(uuid, 0, sizeof(*uuid));
  268. }
  269. }
  270. /* Helper Functions */
  271. /* uuid_create_st -- singlethreaded generation */
  272. static int uuid_create_st(guid_t *uuid)
  273. {
  274. uuid_time_t timestamp;
  275. /* generate new time and save it in the state */
  276. timestamp = update_time ();
  277. /* stuff fields into the UUID */
  278. format_uuid_v1(uuid, timestamp, _state.genstate.clockseq);
  279. return UUID_SUCCESS;
  280. }
  281. /* uuid_create -- multithreaded generation */
  282. static int uuid_create_mt(guid_t *uuid)
  283. {
  284. uuid_time_t timestamp = 0;
  285. unsigned16 clock_seq = 0;
  286. /* just bumps time sequence number. the actual
  287. * time calls are made by a uuid_update_state */
  288. if (update_time_mt(&timestamp, &clock_seq) == UUID_TIME_ERROR)
  289. {
  290. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uuid_create_mt: generator ran "
  291. "out of sequence numbers.\n");
  292. return UUID_TIME_ERROR;
  293. }
  294. /* stuff fields into UUID */
  295. format_uuid_v1(uuid, timestamp, clock_seq);
  296. return UUID_SUCCESS;
  297. }
  298. /* uuid_update_state -- called periodically to update generator's state
  299. (multithreaded case only)
  300. */
  301. static void uuid_update_state (time_t when, void *arg)
  302. {
  303. uuid_time_t timestamp;
  304. get_system_time (&timestamp);
  305. /* time has not changed since last call - return */
  306. if (timestamp == _state.genstate.timestamp)
  307. return;
  308. PR_Lock (_state.lock);
  309. /* clock was set backward - insure uuid uniquness by incrementing clock sequence */
  310. if (timestamp < _state.genstate.timestamp)
  311. _state.genstate.clockseq ++;
  312. _state.genstate.timestamp = timestamp;
  313. _state.time_seq = 0;
  314. PR_Unlock (_state.lock);
  315. }
  316. /* read_state -- read UUID generator state from non-volatile store.
  317. */
  318. static int read_state(const char *configDir, const Slapi_DN *configDN, PRBool *newState)
  319. {
  320. uuid_time_t timestamp;
  321. int rt;
  322. if (configDN)
  323. rt = read_state_from_entry (configDN);
  324. else
  325. rt = read_state_from_file (configDir);
  326. if (rt == UUID_NOTFOUND)
  327. *newState = PR_TRUE;
  328. else
  329. *newState = PR_FALSE;
  330. if (rt != UUID_SUCCESS && rt != UUID_NOTFOUND) /* fatal error - bail out */
  331. {
  332. slapi_log_error (SLAPI_LOG_FATAL, MODULE,
  333. "read_state: failed to get generator's state\n");
  334. return rt;
  335. }
  336. /* get current time and nodeid */
  337. get_system_time(&timestamp);
  338. if (*newState) /* state info is missing - generate */
  339. {
  340. get_node_identifier (&_state.genstate.node);
  341. _state.genstate.clockseq = true_random();
  342. }
  343. else if(_state.genstate.last_update != 1)
  344. {
  345. /* clock sequence should be randomized and not just incremented
  346. because server's clock could have been set back before the
  347. server crashed in which case clock sequence was incremented */
  348. _state.genstate.clockseq = true_random();
  349. }
  350. else if (timestamp <= _state.genstate.timestamp)
  351. {
  352. _state.genstate.clockseq ++;
  353. }
  354. _state.genstate.timestamp = timestamp;
  355. _state.time_seq = 0;
  356. /* need to clear this field so that we know if the state information
  357. is written during shutdown (in which case this flag is set to 1 */
  358. _state.genstate.last_update = 0;
  359. return UUID_SUCCESS;
  360. }
  361. /* read_state_from_file -- read generator state from file.
  362. */
  363. static int read_state_from_file (const char *configDir)
  364. {
  365. char *path;
  366. int rt;
  367. if (configDir == NULL || configDir[0] == '\0')
  368. { /* this directory */
  369. path = (char*)slapi_ch_malloc(strlen (STATE_FILE) + 1);
  370. if (path == NULL)
  371. {
  372. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "read_state: "
  373. "memory allocation failed.\n");
  374. return (UUID_MEMORY_ERROR);
  375. }
  376. strcpy (path, STATE_FILE);
  377. }
  378. else
  379. {
  380. path = slapi_ch_smprintf("%s/%s", configDir, STATE_FILE);
  381. if (path == NULL)
  382. {
  383. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "read_state: "
  384. "memory allocation failed.\n");
  385. return (UUID_MEMORY_ERROR);
  386. }
  387. }
  388. /* open or create state file for read/write and keep it in sync */
  389. _state.fd = PR_Open(path, PR_RDWR | PR_CREATE_FILE | PR_SYNC,
  390. SLAPD_DEFAULT_FILE_MODE);
  391. slapi_ch_free ((void**)&path);
  392. if (!_state.fd)
  393. {
  394. PRErrorCode prerr = PR_GetError();
  395. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "read_state: "
  396. "failed to open state file - %s; " SLAPI_COMPONENT_NAME_NSPR " error %d (%s).\n",
  397. path, prerr, slapd_pr_strerror(prerr));
  398. return (UUID_IO_ERROR);
  399. }
  400. rt = PR_Read (_state.fd, &_state.genstate, sizeof(uuid_gen_state));
  401. if (rt == 0) /* new state */
  402. {
  403. return UUID_NOTFOUND;
  404. }
  405. if (rt == -1)
  406. {
  407. PRErrorCode prerr = PR_GetError();
  408. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "read_state: "
  409. "failed to read state information; " SLAPI_COMPONENT_NAME_NSPR " error %d (%s).\n",
  410. prerr, slapd_pr_strerror(prerr));
  411. return (UUID_IO_ERROR);
  412. }
  413. return(UUID_SUCCESS);
  414. }
  415. /* read_state_from_entry -- read generator state from DIT.
  416. */
  417. static int read_state_from_entry (const Slapi_DN *configDN)
  418. {
  419. Slapi_PBlock *pb;
  420. int res, rt;
  421. Slapi_Entry **entries;
  422. Slapi_Attr *attr;
  423. Slapi_Value *value;
  424. const struct berval *bv;
  425. _state.configDN = slapi_sdn_dup (configDN);
  426. pb = slapi_search_internal(slapi_sdn_get_ndn (configDN), LDAP_SCOPE_BASE,
  427. "objectclass=*", NULL, NULL, 0);
  428. if (pb == NULL)
  429. {
  430. /* the only time NULL pb is returned is when memory allocation fails */
  431. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "read_state_from_entry: "
  432. "NULL pblock returned from search\n");
  433. return UUID_MEMORY_ERROR;
  434. }
  435. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
  436. if (res == LDAP_NO_SUCH_OBJECT)
  437. {
  438. rt = UUID_NOTFOUND;
  439. goto done;
  440. }
  441. if (res != LDAP_SUCCESS)
  442. {
  443. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "read_state_from_entry: "
  444. "search operation failed; LDAP error - %d\n", res);
  445. rt = UUID_LDAP_ERROR;
  446. goto done;
  447. }
  448. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  449. if (entries == NULL || entries[0] == NULL)
  450. {
  451. rt = UUID_UNKNOWN_ERROR;
  452. goto done;
  453. }
  454. /* get state info */
  455. rt = slapi_entry_attr_find (entries[0], STATE_ATTR, &attr);
  456. if (rt != LDAP_SUCCESS)
  457. {
  458. rt = UUID_FORMAT_ERROR;
  459. goto done;
  460. }
  461. slapi_attr_first_value(attr,&value);
  462. if (value == NULL)
  463. {
  464. rt = UUID_FORMAT_ERROR;
  465. goto done;
  466. }
  467. bv = slapi_value_get_berval(value);
  468. if (bv == NULL || bv->bv_val == NULL || bv->bv_len != sizeof (_state.genstate))
  469. {
  470. rt = UUID_FORMAT_ERROR;
  471. goto done;
  472. }
  473. memcpy (&(_state.genstate), bv->bv_val, bv->bv_len);
  474. done:;
  475. if (pb)
  476. {
  477. slapi_free_search_results_internal(pb);
  478. slapi_pblock_destroy(pb);
  479. }
  480. return rt;
  481. }
  482. /* write_state -- save UUID generator state back to non-volatile
  483. storage. Writes immediately to the disk
  484. */
  485. static int write_state (PRBool newState)
  486. {
  487. if (_state.configDN) /* write to DIT */
  488. return write_state_to_entry (newState);
  489. else /* write to a file */
  490. return write_state_to_file ();
  491. }
  492. /* write_state_to_file -- stores state to state file
  493. */
  494. static int write_state_to_file()
  495. {
  496. int rt;
  497. rt = PR_Seek (_state.fd, 0, PR_SEEK_SET);
  498. if (rt == -1)
  499. {
  500. PRErrorCode prerr = PR_GetError();
  501. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "write_state: "
  502. "failed to rewind state file; " SLAPI_COMPONENT_NAME_NSPR " error %d (%s).\n",
  503. prerr, slapd_pr_strerror(prerr));
  504. return UUID_IO_ERROR;
  505. }
  506. rt = PR_Write (_state.fd, &_state.genstate, sizeof (uuid_gen_state));
  507. if (rt == -1)
  508. {
  509. PRErrorCode prerr = PR_GetError();
  510. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "write_state: "
  511. "failed to update state file; " SLAPI_COMPONENT_NAME_NSPR " error %d (%s).\n",
  512. prerr, slapd_pr_strerror(prerr));
  513. return (UUID_IO_ERROR);
  514. }
  515. return (UUID_SUCCESS);
  516. }
  517. /* write_state_to_entry -- stores state to state file
  518. */
  519. static int write_state_to_entry(PRBool newState) {
  520. if (newState)
  521. return add_state_entry ();
  522. else
  523. return modify_state_entry ();
  524. }
  525. /* add_state_entry -- add state entry to the dit */
  526. static int add_state_entry ()
  527. {
  528. struct berval *vals[2];
  529. struct berval val;
  530. Slapi_Entry *e;
  531. Slapi_PBlock *pb = NULL;
  532. int rt;
  533. vals[0] = &val;
  534. vals[1] = NULL;
  535. e = slapi_entry_alloc();
  536. slapi_entry_set_sdn(e, _state.configDN);
  537. /* Set the objectclass attribute */
  538. val.bv_val = "top";
  539. val.bv_len = strlen (val.bv_val);
  540. slapi_entry_add_values(e, "objectclass", vals);
  541. val.bv_val = "extensibleObject";
  542. val.bv_len = strlen (val.bv_val);
  543. slapi_entry_add_values(e, "objectclass", vals);
  544. /* Set state attribute */
  545. val.bv_val = (char*)&(_state.genstate);
  546. val.bv_len = sizeof (_state.genstate);
  547. slapi_entry_add_values(e, STATE_ATTR, vals);
  548. /* this operation frees the entry */
  549. pb = slapi_add_entry_internal(e, 0, 0 /* log_change */);
  550. if (pb == NULL)
  551. {
  552. /* the only time NULL pb is returned is when memory allocation fails */
  553. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "add_state_entry: "
  554. "NULL pblock returned from search\n");
  555. return UUID_MEMORY_ERROR;
  556. }
  557. else
  558. {
  559. slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_RESULT, &rt);
  560. slapi_ch_free((void **) &pb);
  561. }
  562. if (rt != LDAP_SUCCESS)
  563. {
  564. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "add_state_entry: "
  565. "add operation failed; LDAP error - %d.\n", rt);
  566. return UUID_LDAP_ERROR;
  567. }
  568. slapi_log_error (SLAPI_LOG_HOUSE, MODULE, "add_state_entry: "
  569. "successfully added generator's state entry");
  570. return UUID_SUCCESS;
  571. }
  572. /* modify_state_entry -- modify state entry in the dit */
  573. static int modify_state_entry ()
  574. {
  575. int res;
  576. Slapi_Mods mods;
  577. struct berval *vals[2];
  578. struct berval val;
  579. Slapi_PBlock *pb;
  580. val.bv_val = (char*)&(_state.genstate);
  581. val.bv_len = sizeof (_state.genstate);
  582. vals[0] = &val;
  583. vals[1] = NULL;
  584. slapi_mods_init (&mods, 1);
  585. slapi_mods_add_modbvps(&mods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, STATE_ATTR, vals);
  586. pb = slapi_modify_internal(slapi_sdn_get_ndn (_state.configDN),
  587. slapi_mods_get_ldapmods_byref(&mods), NULL, 0);
  588. slapi_mods_done(&mods);
  589. if (pb == NULL)
  590. {
  591. /* the only time NULL pb is returned is when memory allocation fails */
  592. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "modify_state_entry: "
  593. "NULL pblock returned from search\n");
  594. return UUID_MEMORY_ERROR;
  595. }
  596. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
  597. slapi_pblock_destroy(pb);
  598. if (res != LDAP_SUCCESS)
  599. {
  600. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "modify_state_entry: "
  601. "update operation failed; LDAP error - %d.\n", res);
  602. return UUID_LDAP_ERROR;
  603. }
  604. slapi_log_error (SLAPI_LOG_HOUSE, MODULE, "modify_state_entry: "
  605. "successfully updated generator's state entry");
  606. return UUID_SUCCESS;
  607. }
  608. /* update_time -- updates time portion of the generators state
  609. for singlethreaded generation
  610. */
  611. static uuid_time_t update_time()
  612. {
  613. uuid_time_t time_now;
  614. get_system_time(&time_now);
  615. /* time was turned back - need to change clocksequence */
  616. if (time_now < _state.genstate.timestamp)
  617. {
  618. _state.genstate.clockseq ++;
  619. _state.genstate.timestamp = time_now;
  620. _state.time_seq = 0;
  621. return _state.genstate.timestamp;
  622. }
  623. /* go into loop if the time has not changed since last call */
  624. while (time_now == _state.genstate.timestamp)
  625. {
  626. /* if we still have sequence numbers to give to the
  627. timestamp, use it and get out of the loop */
  628. if (_state.time_seq < SEQ_PER_SEC - 1)
  629. {
  630. _state.time_seq ++;
  631. break;
  632. }
  633. /* this should never happen because we don't generate more that 10 mln ids/sec */
  634. DS_Sleep (PR_MillisecondsToInterval(500));
  635. get_system_time(&time_now);
  636. }
  637. /* system time has changed - clear sequence number and
  638. update last time */
  639. if (time_now > _state.genstate.timestamp)
  640. {
  641. _state.time_seq = 0;
  642. _state.genstate.timestamp = time_now;
  643. }
  644. return _state.genstate.timestamp + _state.time_seq;
  645. }
  646. /* update_time_mt -- this function updates time sequence part of generators state.
  647. This function should be used in the multithreaded environment
  648. only.
  649. */
  650. static int update_time_mt (uuid_time_t *timestamp, unsigned16 *clock_seq)
  651. {
  652. PR_Lock (_state.lock);
  653. /* we ran out time sequence numbers because
  654. uuid_update_state function is not called
  655. frequently enough */
  656. if (_state.time_seq >= SEQ_PER_SEC - 1)
  657. {
  658. _state.time_seq = NEED_TIME_UPDATE;
  659. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "update_time_mt: "
  660. "ran out of time sequence numbers; "
  661. "uuid_update_state must be called\n");
  662. PR_Unlock (_state.lock);
  663. return (UUID_TIME_ERROR);
  664. }
  665. _state.time_seq++;
  666. *timestamp = _state.genstate.timestamp + _state.time_seq;
  667. *clock_seq = _state.genstate.clockseq;
  668. PR_Unlock (_state.lock);
  669. return UUID_SUCCESS;
  670. }
  671. /* format_uuid_v1 -- make a UUID from the timestamp, clockseq,
  672. and node ID
  673. */
  674. static void format_uuid_v1(guid_t * uuid, uuid_time_t timestamp, unsigned16 clock_seq)
  675. {
  676. /* Construct a version 1 uuid with the information we've gathered
  677. * plus a few constants. */
  678. uuid->time_low = (unsigned32)(timestamp & 0xFFFFFFFF);
  679. uuid->time_mid = (unsigned16)((timestamp >> 32) & 0xFFFF);
  680. uuid->time_hi_and_version = (unsigned16)
  681. ((timestamp >> 48) & 0x0FFF);
  682. uuid->time_hi_and_version |= (1 << 12);
  683. uuid->clock_seq_low = clock_seq & 0xFF;
  684. uuid->clock_seq_hi_and_reserved = (unsigned8)((clock_seq & 0x3F00) >> 8);
  685. uuid->clock_seq_hi_and_reserved |= 0x80;
  686. memcpy(&uuid->node, &_state.genstate.node, sizeof (uuid->node));
  687. }
  688. /* when converting broken values, we may need to swap the bytes */
  689. #define BSWAP16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
  690. #define BSWAP32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
  691. (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
  692. /* format_uuid_v3 -- make a UUID from a (pseudo)random 128 bit number
  693. */
  694. static void format_uuid_v3(guid_t * uuid, unsigned char hash[16])
  695. {
  696. char *use_broken_uuid = getenv("USE_BROKEN_UUID");
  697. /* Construct a version 3 uuid with the (pseudo-)random number
  698. * plus a few constants. */
  699. memcpy(uuid, hash, sizeof(guid_t));
  700. /* when migrating, we skip the ntohl in order to read in old,
  701. incorrectly formatted uuids */
  702. if (!use_broken_uuid || (*use_broken_uuid == '0')) {
  703. /* convert UUID to local byte order */
  704. uuid->time_low = PR_ntohl(uuid->time_low);
  705. uuid->time_mid = PR_ntohs(uuid->time_mid);
  706. uuid->time_hi_and_version = PR_ntohs(uuid->time_hi_and_version);
  707. } else {
  708. #if defined(IS_BIG_ENDIAN)
  709. /* convert UUID to b0rken byte order */
  710. uuid->time_low = BSWAP32(uuid->time_low);
  711. uuid->time_mid = BSWAP16(uuid->time_mid);
  712. uuid->time_hi_and_version = BSWAP16(uuid->time_hi_and_version);
  713. #endif
  714. }
  715. /* put in the variant and version bits */
  716. uuid->time_hi_and_version &= 0x0FFF;
  717. uuid->time_hi_and_version |= (3 << 12);
  718. uuid->clock_seq_hi_and_reserved &= 0x3F;
  719. uuid->clock_seq_hi_and_reserved |= 0x80;
  720. }
  721. /* system dependent call to get IEEE node ID.
  722. This sample implementation generates a random node ID
  723. Assumes that configDir was tested for validity by
  724. the higher layer
  725. */
  726. static int get_node_identifier (uuid_node_t *node)
  727. {
  728. unsigned char seed[SEED_LENGTH]= {0};
  729. #ifdef USE_NIC
  730. /* ONREPL - code to use NIC address would go here; Currently, we use
  731. cryptographic random number to avoid state sharing among
  732. servers running on the same host. See UniqueID Generator
  733. docs for more info.
  734. */
  735. #endif
  736. get_random_info(seed, SEED_LENGTH);
  737. seed[0] |= 0x80;
  738. memcpy (node, seed, sizeof (uuid_node_t));
  739. return UUID_SUCCESS;
  740. }
  741. /* call to get the current system time. Returned as 100ns ticks
  742. since Oct 15, 1582, but resolution may be less than 100ns.
  743. */
  744. static void get_system_time(uuid_time_t *uuid_time)
  745. {
  746. time_t cur_time;
  747. cur_time = current_time ();
  748. /* Offset between UUID formatted times and time() formatted times.
  749. UUID UTC base time is October 15, 1582. time() base time is January 1, 1970.*/
  750. *uuid_time = cur_time * SEQ_PER_SEC + I64(0x01B21DD213814000);
  751. }
  752. /* ONREPL */
  753. /* true_random -- generate a crypto-quality random number.
  754. */
  755. static unsigned16 true_random(void)
  756. {
  757. static int inited = 0;
  758. if (!inited)
  759. {
  760. uuid_seed = slapi_rand();
  761. inited = 1;
  762. }
  763. return (slapi_rand_r(&uuid_seed));
  764. }
  765. static void get_random_info(unsigned char seed[], size_t arraylen)
  766. {
  767. slapi_rand_array(seed, arraylen);
  768. }