"Fossies" - the Fresh Open Source Software Archive

Member "netxms-3.8.166/src/libnetxms/uuid.cpp" (23 Feb 2021, 6833 Bytes) of package /linux/misc/netxms-3.8.166.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "uuid.cpp" see the Fossies "Dox" file reference documentation.

    1 /* 
    2 ** libuuid integrated into NetXMS project
    3 ** Copyright (C) 1996, 1997 Theodore Ts'o.
    4 ** Integrated into NetXMS by Victor Kirhenshtein
    5 **
    6 ** This program is free software; you can redistribute it and/or modify
    7 ** it under the terms of the GNU Lesser General Public License as published
    8 ** by the Free Software Foundation; either version 3 of the License, or
    9 ** (at your option) any later version.
   10 **
   11 ** This program is distributed in the hope that it will be useful,
   12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 ** GNU General Public License for more details.
   15 **
   16 ** You should have received a copy of the GNU Lesser General Public License
   17 ** along with this program; if not, write to the Free Software
   18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   19 **
   20 ** File: uuid.cpp
   21 **
   22 **/
   23 
   24 #include "libnetxms.h"
   25 #include <uuid.h>
   26 
   27 #if _WITH_ENCRYPTION
   28 #include <openssl/rand.h>
   29 #endif
   30 
   31 /**
   32  * NULL GUID
   33  */
   34 const uuid __EXPORT uuid::NULL_UUID = uuid();
   35 
   36 /*
   37  * Offset between 15-Oct-1582 and 1-Jan-70
   38  */
   39 #define TIME_OFFSET_HIGH 0x01B21DD2
   40 #define TIME_OFFSET_LOW  0x13814000
   41 
   42 /**
   43  * Unpacked UUID structure
   44  */
   45 struct __uuid
   46 {
   47     uint32_t    time_low;
   48     uint16_t time_mid;
   49     uint16_t time_hi_and_version;
   50     uint16_t clock_seq;
   51     uint8_t node[6];
   52 };
   53 
   54 /**
   55  * Internal routine for packing UUID's
   56  */
   57 static void uuid_pack(struct __uuid *uu, uuid_t ptr)
   58 {
   59     uint32_t tmp;
   60     uint8_t *out = ptr;
   61 
   62     tmp = uu->time_low;
   63     out[3] = (uint8_t)tmp;
   64     tmp >>= 8;
   65     out[2] = (uint8_t)tmp;
   66     tmp >>= 8;
   67     out[1] = (uint8_t)tmp;
   68     tmp >>= 8;
   69     out[0] = (uint8_t)tmp;
   70     
   71     tmp = uu->time_mid;
   72     out[5] = (uint8_t)tmp;
   73     tmp >>= 8;
   74     out[4] = (uint8_t)tmp;
   75 
   76     tmp = uu->time_hi_and_version;
   77     out[7] = (uint8_t)tmp;
   78     tmp >>= 8;
   79     out[6] = (uint8_t)tmp;
   80 
   81     tmp = uu->clock_seq;
   82     out[9] = (uint8_t)tmp;
   83     tmp >>= 8;
   84     out[8] = (uint8_t)tmp;
   85 
   86     memcpy(out + 10, uu->node, 6);
   87 }
   88 
   89 /**
   90  * Internal routine for unpacking UUID
   91  */
   92 static void uuid_unpack(const uuid_t in, struct __uuid *uu)
   93 {
   94     const uint8_t *ptr = in;
   95     uint32_t tmp;
   96 
   97     tmp = *ptr++;
   98     tmp = (tmp << 8) | *ptr++;
   99     tmp = (tmp << 8) | *ptr++;
  100     tmp = (tmp << 8) | *ptr++;
  101     uu->time_low = tmp;
  102 
  103     tmp = *ptr++;
  104     tmp = (tmp << 8) | *ptr++;
  105     uu->time_mid = tmp;
  106     
  107     tmp = *ptr++;
  108     tmp = (tmp << 8) | *ptr++;
  109     uu->time_hi_and_version = tmp;
  110 
  111     tmp = *ptr++;
  112     tmp = (tmp << 8) | *ptr++;
  113     uu->clock_seq = tmp;
  114 
  115     memcpy(uu->node, ptr, 6);
  116 }
  117 
  118 /**
  119  * Clear a UUID
  120  */
  121 void LIBNETXMS_EXPORTABLE _uuid_clear(uuid_t uu)
  122 {
  123     memset(uu, 0, 16);
  124 }
  125 
  126 #define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
  127 
  128 /**
  129  * compare whether or not two UUID's are the same
  130  *
  131  * Returns 1/-1 if the two UUID's are different, and 0 if they are the same.
  132  */
  133 int LIBNETXMS_EXPORTABLE _uuid_compare(const uuid_t uu1, const uuid_t uu2)
  134 {
  135     struct __uuid   uuid1, uuid2;
  136 
  137     uuid_unpack(uu1, &uuid1);
  138     uuid_unpack(uu2, &uuid2);
  139 
  140     UUCMP(uuid1.time_low, uuid2.time_low);
  141     UUCMP(uuid1.time_mid, uuid2.time_mid);
  142     UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
  143     UUCMP(uuid1.clock_seq, uuid2.clock_seq);
  144     return memcmp(uuid1.node, uuid2.node, 6);
  145 }
  146 
  147 /**
  148  * isnull.c --- Check whether or not the UUID is null
  149  * Returns true if the uuid is the NULL uuid
  150  */
  151 bool LIBNETXMS_EXPORTABLE _uuid_is_null(const uuid_t uu)
  152 {
  153     const uint8_t *cp = uu;
  154     for (int i = 0; i < 16; i++)
  155         if (*cp++)
  156             return false;
  157     return true;
  158 }
  159 
  160 /**
  161  * Parse UUID
  162  */
  163 int LIBNETXMS_EXPORTABLE _uuid_parse(const TCHAR *in, uuid_t uu)
  164 {
  165     struct __uuid uuid;
  166     int i;
  167     const TCHAR *cp;
  168     TCHAR buf[3];
  169 
  170     if (_tcslen(in) != 36)
  171         return -1;
  172     for (i=0, cp = in; i <= 36; i++,cp++) {
  173         if ((i == 8) || (i == 13) || (i == 18) ||
  174             (i == 23))
  175             if (*cp == _T('-'))
  176                 continue;
  177         if (i == 36)
  178             if (*cp == 0)
  179                 continue;
  180         if (!_istxdigit(*cp))
  181             return -1;
  182     }
  183     uuid.time_low = _tcstoul(in, NULL, 16);
  184     uuid.time_mid = (WORD)_tcstoul(in + 9, NULL, 16);
  185     uuid.time_hi_and_version = (WORD)_tcstoul(in + 14, NULL, 16);
  186     uuid.clock_seq = (WORD)_tcstoul(in + 19, NULL, 16);
  187     cp = in + 24;
  188     buf[2] = 0;
  189     for(i = 0; i < 6; i++)
  190    {
  191         buf[0] = *cp++;
  192         buf[1] = *cp++;
  193         uuid.node[i] = (BYTE)_tcstoul(buf, NULL, 16);
  194     }
  195     
  196     uuid_pack(&uuid, uu);
  197     return 0;
  198 }
  199 
  200 /**
  201  * Convert packed UUID to string
  202  */
  203 TCHAR LIBNETXMS_EXPORTABLE *_uuid_to_string(const uuid_t uu, TCHAR *out)
  204 {
  205     struct __uuid uuid;
  206     uuid_unpack(uu, &uuid);
  207     _sntprintf(out, 37,
  208         _T("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
  209         uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
  210         uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
  211         uuid.node[0], uuid.node[1], uuid.node[2],
  212         uuid.node[3], uuid.node[4], uuid.node[5]);
  213    return out;
  214 }
  215 
  216 #ifdef UNICODE
  217 
  218 /**
  219  * Convert packed UUID to string (non-UNICODE version)
  220  */
  221 char LIBNETXMS_EXPORTABLE *_uuid_to_stringA(const uuid_t uu, char *out)
  222 {
  223    struct __uuid uuid;
  224    uuid_unpack(uu, &uuid);
  225    snprintf(out, 37,
  226       "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  227       uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
  228       uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
  229       uuid.node[0], uuid.node[1], uuid.node[2],
  230       uuid.node[3], uuid.node[4], uuid.node[5]);
  231    return out;
  232 }
  233 
  234 #endif
  235 
  236 #ifndef _WIN32
  237 
  238 static int get_random_fd()
  239 {
  240    int fd = open("/dev/urandom", O_RDONLY);
  241    if (fd == -1)
  242       fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
  243     return fd;
  244 }
  245 
  246 /*
  247  * Generate a series of random bytes.  Use /dev/urandom if possible,
  248  * and if not, use srandom/random.
  249  */
  250 static void get_random_bytes(void *buf, int nbytes)
  251 {
  252 #if _WITH_ENCRYPTION
  253    if (RAND_bytes(static_cast<unsigned char*>(buf), nbytes))
  254       return;
  255 #endif
  256 
  257     char *cp = (char *)buf;
  258    int fd = get_random_fd();
  259     if (fd >= 0)
  260    {
  261        int lose_counter = 0;
  262 
  263         while (nbytes > 0)
  264       {
  265             int i = read(fd, cp, nbytes);
  266             if ((i < 0) &&
  267                 ((errno == EINTR) || (errno == EAGAIN)))
  268                 continue;
  269             if (i <= 0)
  270             {
  271                 if (lose_counter++ == 8)
  272                     break;
  273                 continue;
  274             }
  275             nbytes -= i;
  276             cp += i;
  277             lose_counter = 0;
  278         }
  279         close(fd);
  280     }
  281     if (nbytes == 0)
  282         return;
  283 
  284     // Use libc rand() as last resort
  285     for(int i = 0; i < nbytes; i++)
  286         *cp++ = rand() & 0xFF;
  287 }
  288 
  289 static void uuid_generate_random(uuid_t out)
  290 {
  291     uuid_t  buf;
  292     struct __uuid uu;
  293 
  294     get_random_bytes(buf, sizeof(buf));
  295     uuid_unpack(buf, &uu);
  296 
  297     uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
  298     uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
  299     uuid_pack(&uu, out);
  300 }
  301 
  302 #endif  /* _WIN32 */
  303 
  304 /*
  305  * This is the generic front-end to uuid_generate_random and
  306  * uuid_generate_time.  It uses uuid_generate_random only if
  307  * /dev/urandom is available, since otherwise we won't have
  308  * high-quality randomness.
  309  */
  310 void LIBNETXMS_EXPORTABLE _uuid_generate(uuid_t out)
  311 {
  312 #ifdef _WIN32
  313     UUID uuid;
  314     UuidCreate(&uuid);
  315     memcpy(out, &uuid, UUID_LENGTH);
  316 #else
  317    uuid_generate_random(out);
  318 #endif
  319 }