Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

gw_uuid.c File Reference

#include "gw-config.h"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include "gwlib/gw_uuid_types.h"
#include "gwlib/gw_uuid.h"

Include dependency graph for gw_uuid.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  uuid

Defines

#define TIME_OFFSET_HIGH   0x01B21DD2
#define TIME_OFFSET_LOW   0x13814000
#define srand(x)   srandom(x)
#define rand()   random()
#define UUCMP(u1, u2)   if (u1 != u2) return((u1 < u2) ? -1 : 1);
#define ifreq_size(i)   sizeof(struct ifreq)
#define MAX_ADJUSTMENT   10

Functions

void uuid_pack (const struct uuid *uu, uuid_t ptr)
void uuid_unpack (const uuid_t in, struct uuid *uu)
int get_random_fd (void)
void uuid_init (void)
void uuid_shutdown (void)
void uuid_clear (uuid_t uu)
int uuid_compare (const uuid_t uu1, const uuid_t uu2)
void uuid_copy (uuid_t dst, const uuid_t src)
void get_random_bytes (void *buf, int nbytes)
int get_node_id (unsigned char *node_id)
int get_clock (__u32 *clock_high, __u32 *clock_low, __u16 *ret_clock_seq)
void uuid_generate_time (uuid_t out)
void uuid_generate_random (uuid_t out)
void uuid_generate (uuid_t out)
int uuid_is_null (const uuid_t uu)
int uuid_parse (const char *in, uuid_t uu)
void uuid_unparse (const uuid_t uu, char *out)
time_t uuid_time (const uuid_t uu, struct timeval *ret_tv)
int uuid_type (const uuid_t uu)
int uuid_variant (const uuid_t uu)


Define Documentation

#define ifreq_size  )     sizeof(struct ifreq)
 

Referenced by get_node_id().

#define MAX_ADJUSTMENT   10
 

Definition at line 302 of file gw_uuid.c.

 
#define rand  )     random()
 

Definition at line 81 of file gw_uuid.c.

Referenced by get_random_bytes(), get_random_fd(), and gw_rand().

#define srand  )     srandom(x)
 

Definition at line 80 of file gw_uuid.c.

Referenced by get_random_fd(), and main().

#define TIME_OFFSET_HIGH   0x01B21DD2
 

Definition at line 59 of file gw_uuid.c.

#define TIME_OFFSET_LOW   0x13814000
 

Definition at line 60 of file gw_uuid.c.

#define UUCMP u1,
u2   )     if (u1 != u2) return((u1 < u2) ? -1 : 1);
 

Definition at line 124 of file gw_uuid.c.

Referenced by uuid_compare().


Function Documentation

int get_clock __u32 clock_high,
__u32 clock_low,
__u16 ret_clock_seq
[static]
 

Definition at line 304 of file gw_uuid.c.

References __u16, and get_random_bytes().

Referenced by uuid_generate_time().

00305 {
00306     static int          adjustment = 0;
00307     static struct timeval       last = {0, 0};
00308     static __u16            clock_seq;
00309     struct timeval          tv;
00310     unsigned long long      clock_reg;
00311     
00312 try_again:
00313     gettimeofday(&tv, 0);
00314     if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
00315         get_random_bytes(&clock_seq, sizeof(clock_seq));
00316         clock_seq &= 0x1FFF;
00317         last = tv;
00318         last.tv_sec--;
00319     }
00320     if ((tv.tv_sec < last.tv_sec) ||
00321         ((tv.tv_sec == last.tv_sec) &&
00322          (tv.tv_usec < last.tv_usec))) {
00323         clock_seq = (clock_seq+1) & 0x1FFF;
00324         adjustment = 0;
00325         last = tv;
00326     } else if ((tv.tv_sec == last.tv_sec) &&
00327         (tv.tv_usec == last.tv_usec)) {
00328         if (adjustment >= MAX_ADJUSTMENT)
00329             goto try_again;
00330         adjustment++;
00331     } else {
00332         adjustment = 0;
00333         last = tv;
00334     }
00335         
00336     clock_reg = tv.tv_usec*10 + adjustment;
00337     clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
00338     clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
00339 
00340     *clock_high = clock_reg >> 32;
00341     *clock_low = clock_reg;
00342     *ret_clock_seq = clock_seq;
00343     return 0;
00344 }

Here is the call graph for this function:

int get_node_id unsigned char *  node_id  )  [static]
 

Definition at line 229 of file gw_uuid.c.

References ifreq_size.

Referenced by uuid_generate_time().

00230 {
00231 #ifdef HAVE_NET_IF_H
00232     int         sd;
00233     struct ifreq    ifr, *ifrp;
00234     struct ifconf   ifc;
00235     char buf[1024];
00236     int     n, i;
00237     unsigned char   *a;
00238     
00239 /*
00240  * BSD 4.4 defines the size of an ifreq to be
00241  * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
00242  * However, under earlier systems, sa_len isn't present, so the size is 
00243  * just sizeof(struct ifreq)
00244  */
00245 #ifdef HAVE_SA_LEN
00246 #ifndef max
00247 #define max(a,b) ((a) > (b) ? (a) : (b))
00248 #endif
00249 #define ifreq_size(i) max(sizeof(struct ifreq),\
00250      sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
00251 #else
00252 #define ifreq_size(i) sizeof(struct ifreq)
00253 #endif /* HAVE_SA_LEN*/
00254 
00255     sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
00256     if (sd < 0) {
00257         return -1;
00258     }
00259     memset(buf, 0, sizeof(buf));
00260     ifc.ifc_len = sizeof(buf);
00261     ifc.ifc_buf = buf;
00262     if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
00263         close(sd);
00264         return -1;
00265     }
00266     n = ifc.ifc_len;
00267     for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
00268         ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
00269         strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
00270 #ifdef SIOCGIFHWADDR
00271         if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
00272             continue;
00273         a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
00274 #else
00275 #ifdef SIOCGENADDR
00276         if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
00277             continue;
00278         a = (unsigned char *) ifr.ifr_enaddr;
00279 #else
00280         /*
00281          * XXX we don't have a way of getting the hardware
00282          * address
00283          */
00284         close(sd);
00285         return 0;
00286 #endif /* SIOCGENADDR */
00287 #endif /* SIOCGIFHWADDR */
00288         if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
00289             continue;
00290         if (node_id) {
00291             memcpy(node_id, a, 6);
00292             close(sd);
00293             return 1;
00294         }
00295     }
00296     close(sd);
00297 #endif
00298     return 0;
00299 }

void get_random_bytes void *  buf,
int  nbytes
[static]
 

Definition at line 197 of file gw_uuid.c.

References get_random_fd(), and rand.

Referenced by get_clock(), uuid_generate_random(), and uuid_generate_time().

00198 {
00199     int i, n = nbytes, fd = get_random_fd();
00200     int lose_counter = 0;
00201     unsigned char *cp = (unsigned char *) buf;
00202 
00203     if (fd >= 0) {
00204         while (n > 0) {
00205             i = read(fd, cp, n);
00206             if (i <= 0) {
00207                 if (lose_counter++ > 16)
00208                     break;
00209                 continue;
00210             }
00211             n -= i;
00212             cp += i;
00213             lose_counter = 0;
00214         }
00215     }
00216     
00217     /*
00218      * We do this all the time, but this is the only source of
00219      * randomness if /dev/random/urandom is out to lunch.
00220      */
00221     for (cp = buf, i = 0; i < nbytes; i++)
00222         *cp++ ^= (rand() >> 7) & 0xFF;
00223     return;
00224 }

Here is the call graph for this function:

int get_random_fd void   )  [static]
 

Definition at line 171 of file gw_uuid.c.

References rand, and srand.

Referenced by get_random_bytes(), uuid_generate(), uuid_init(), and uuid_shutdown().

00172 {
00173     struct timeval  tv;
00174     static int  fd = -2;
00175     int     i;
00176 
00177     if (fd == -2) {
00178         gettimeofday(&tv, 0);
00179         fd = open("/dev/urandom", O_RDONLY);
00180         if (fd == -1)
00181             fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
00182         srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
00183     }
00184     /* Crank the random number generator a few times */
00185     gettimeofday(&tv, 0);
00186     for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
00187         rand();
00188 
00189     return fd;
00190 }

void uuid_clear uuid_t  uu  ) 
 

Definition at line 105 of file gw_uuid.c.

Referenced by main().

00106 {
00107     memset(uu, 0, 16);
00108 }

int uuid_compare const uuid_t  uu1,
const uuid_t  uu2
 

Definition at line 126 of file gw_uuid.c.

References uuid::clock_seq, uuid::node, uuid::time_hi_and_version, uuid::time_low, uuid::time_mid, UUCMP, and uuid_unpack().

00127 {
00128     struct uuid uuid1, uuid2;
00129 
00130     uuid_unpack(uu1, &uuid1);
00131     uuid_unpack(uu2, &uuid2);
00132 
00133     UUCMP(uuid1.time_low, uuid2.time_low);
00134     UUCMP(uuid1.time_mid, uuid2.time_mid);
00135     UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
00136     UUCMP(uuid1.clock_seq, uuid2.clock_seq);
00137     return memcmp(uuid1.node, uuid2.node, 6);
00138 }

Here is the call graph for this function:

void uuid_copy uuid_t  dst,
const uuid_t  src
 

Definition at line 150 of file gw_uuid.c.

Referenced by boxc_receiver(), deliver_sms_to_queue(), obey_request_thread(), store_file_save_ack(), and store_spool_save_ack().

00151 {
00152     unsigned char       *cp1;
00153     const unsigned char *cp2;
00154     int         i;
00155 
00156     for (i=0, cp1 = dst, cp2 = src; i < 16; i++)
00157         *cp1++ = *cp2++;
00158 }

void uuid_generate uuid_t  out  ) 
 

Definition at line 392 of file gw_uuid.c.

References get_random_fd(), uuid_generate_random(), and uuid_generate_time().

Referenced by check_concatenation(), main(), sms_split(), soap_send_loop(), store_spool_save(), and store_to_dict().

00393 {
00394     if (get_random_fd() >= 0) {
00395         uuid_generate_random(out);
00396     }
00397     else
00398         uuid_generate_time(out);
00399 }

Here is the call graph for this function:

void uuid_generate_random uuid_t  out  ) 
 

Definition at line 373 of file gw_uuid.c.

References uuid::clock_seq, get_random_bytes(), uuid::time_hi_and_version, uuid_pack(), uuid_t, and uuid_unpack().

Referenced by uuid_generate().

00374 {
00375     uuid_t  buf;
00376     struct uuid uu;
00377 
00378     get_random_bytes(buf, sizeof(buf));
00379     uuid_unpack(buf, &uu);
00380 
00381     uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
00382     uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
00383     uuid_pack(&uu, out);
00384 }

Here is the call graph for this function:

void uuid_generate_time uuid_t  out  ) 
 

Definition at line 346 of file gw_uuid.c.

References __u32, uuid::clock_seq, get_clock(), get_node_id(), get_random_bytes(), uuid::node, uuid::time_hi_and_version, uuid::time_low, uuid::time_mid, and uuid_pack().

Referenced by uuid_generate().

00347 {
00348     static unsigned char node_id[6];
00349     static int has_init = 0;
00350     struct uuid uu;
00351     __u32   clock_mid;
00352 
00353     if (!has_init) {
00354         if (get_node_id(node_id) <= 0) {
00355             get_random_bytes(node_id, 6);
00356             /*
00357              * Set multicast bit, to prevent conflicts
00358              * with IEEE 802 addresses obtained from
00359              * network cards
00360              */
00361             node_id[0] |= 0x80;
00362         }
00363         has_init = 1;
00364     }
00365     get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
00366     uu.clock_seq |= 0x8000;
00367     uu.time_mid = (__u16) clock_mid;
00368     uu.time_hi_and_version = (clock_mid >> 16) | 0x1000;
00369     memcpy(uu.node, node_id, 6);
00370     uuid_pack(&uu, out);
00371 }

Here is the call graph for this function:

void uuid_init void   ) 
 

Definition at line 86 of file gw_uuid.c.

References get_random_fd().

Referenced by gwlib_init().

00087 {
00088     /* 
00089      * open random device if any.
00090      * We should do it here because otherwise it's
00091      * possible that we open device twice.
00092      */
00093     get_random_fd();
00094 }

Here is the call graph for this function:

int uuid_is_null const uuid_t  uu  ) 
 

Definition at line 412 of file gw_uuid.c.

Referenced by get_pattern(), soap_send_loop(), store_spool_save(), store_to_dict(), and urltrans_fill_escape_codes().

00413 {
00414     const unsigned char     *cp;
00415     int         i;
00416 
00417     for (i=0, cp = uu; i < 16; i++)
00418         if (*cp++)
00419             return 0;
00420     return 1;
00421 }

void uuid_pack const struct uuid uu,
uuid_t  ptr
[static]
 

Definition at line 433 of file gw_uuid.c.

References __u32, uuid::clock_seq, uuid::node, uuid::time_hi_and_version, uuid::time_low, and uuid::time_mid.

Referenced by uuid_generate_random(), uuid_generate_time(), and uuid_parse().

00434 {
00435     __u32   tmp;
00436     unsigned char   *out = ptr;
00437 
00438     tmp = uu->time_low;
00439     out[3] = (unsigned char) tmp;
00440     tmp >>= 8;
00441     out[2] = (unsigned char) tmp;
00442     tmp >>= 8;
00443     out[1] = (unsigned char) tmp;
00444     tmp >>= 8;
00445     out[0] = (unsigned char) tmp;
00446     
00447     tmp = uu->time_mid;
00448     out[5] = (unsigned char) tmp;
00449     tmp >>= 8;
00450     out[4] = (unsigned char) tmp;
00451 
00452     tmp = uu->time_hi_and_version;
00453     out[7] = (unsigned char) tmp;
00454     tmp >>= 8;
00455     out[6] = (unsigned char) tmp;
00456 
00457     tmp = uu->clock_seq;
00458     out[9] = (unsigned char) tmp;
00459     tmp >>= 8;
00460     out[8] = (unsigned char) tmp;
00461 
00462     memcpy(out+10, uu->node, 6);
00463 }

int uuid_parse const char *  in,
uuid_t  uu
 

Definition at line 475 of file gw_uuid.c.

References uuid::clock_seq, uuid::node, uuid::time_hi_and_version, uuid::time_low, uuid::time_mid, and uuid_pack().

Referenced by parse_uuid().

00476 {
00477     struct uuid uuid;
00478     int         i;
00479     const char  *cp;
00480     char        buf[3];
00481 
00482     if (strlen(in) != 36)
00483         return -1;
00484     for (i=0, cp = in; i <= 36; i++,cp++) {
00485         if ((i == 8) || (i == 13) || (i == 18) ||
00486             (i == 23)) {
00487             if (*cp == '-')
00488                 continue;
00489             else
00490                 return -1;
00491         }
00492         if (i== 36)
00493             if (*cp == 0)
00494                 continue;
00495         if (!isxdigit(*cp))
00496             return -1;
00497     }
00498     uuid.time_low = strtoul(in, NULL, 16);
00499     uuid.time_mid = strtoul(in+9, NULL, 16);
00500     uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
00501     uuid.clock_seq = strtoul(in+19, NULL, 16);
00502     cp = in+24;
00503     buf[2] = 0;
00504     for (i=0; i < 6; i++) {
00505         buf[0] = *cp++;
00506         buf[1] = *cp++;
00507         uuid.node[i] = strtoul(buf, NULL, 16);
00508     }
00509     
00510     uuid_pack(&uuid, uu);
00511     return 0;
00512 }

Here is the call graph for this function:

void uuid_shutdown void   ) 
 

Definition at line 97 of file gw_uuid.c.

References get_random_fd().

Referenced by gwlib_shutdown().

00098 {
00099     int fd = get_random_fd();
00100 
00101     if (fd > 0)
00102         close(fd);
00103 }

Here is the call graph for this function:

time_t uuid_time const uuid_t  uu,
struct timeval *  ret_tv
 

Definition at line 586 of file gw_uuid.c.

References __u32, uuid::time_hi_and_version, uuid::time_low, uuid::time_mid, and uuid_unpack().

00587 {
00588     struct uuid     uuid;
00589     __u32           high;
00590     struct timeval      tv;
00591     unsigned long long  clock_reg;
00592 
00593     uuid_unpack(uu, &uuid);
00594     
00595     high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
00596     clock_reg = uuid.time_low | ((unsigned long long) high << 32);
00597 
00598     clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
00599     tv.tv_sec = clock_reg / 10000000;
00600     tv.tv_usec = (clock_reg % 10000000) / 10;
00601 
00602     if (ret_tv)
00603         *ret_tv = tv;
00604 
00605     return tv.tv_sec;
00606 }

Here is the call graph for this function:

int uuid_type const uuid_t  uu  ) 
 

Definition at line 608 of file gw_uuid.c.

References uuid::time_hi_and_version, and uuid_unpack().

00609 {
00610     struct uuid     uuid;
00611 
00612     uuid_unpack(uu, &uuid); 
00613     return ((uuid.time_hi_and_version >> 12) & 0xF);
00614 }

Here is the call graph for this function:

void uuid_unpack const uuid_t  in,
struct uuid uu
[static]
 

Definition at line 525 of file gw_uuid.c.

References __u32, __u8, uuid::clock_seq, uuid::node, uuid::time_hi_and_version, uuid::time_low, and uuid::time_mid.

Referenced by uuid_compare(), uuid_generate_random(), uuid_time(), uuid_type(), uuid_unparse(), and uuid_variant().

00526 {
00527     const __u8  *ptr = in;
00528     __u32       tmp;
00529 
00530     tmp = *ptr++;
00531     tmp = (tmp << 8) | *ptr++;
00532     tmp = (tmp << 8) | *ptr++;
00533     tmp = (tmp << 8) | *ptr++;
00534     uu->time_low = tmp;
00535 
00536     tmp = *ptr++;
00537     tmp = (tmp << 8) | *ptr++;
00538     uu->time_mid = tmp;
00539     
00540     tmp = *ptr++;
00541     tmp = (tmp << 8) | *ptr++;
00542     uu->time_hi_and_version = tmp;
00543 
00544     tmp = *ptr++;
00545     tmp = (tmp << 8) | *ptr++;
00546     uu->clock_seq = tmp;
00547 
00548     memcpy(uu->node, ptr, 6);
00549 }

void uuid_unparse const uuid_t  uu,
char *  out
 

Definition at line 561 of file gw_uuid.c.

References uuid::clock_seq, uuid::node, uuid::time_hi_and_version, uuid::time_low, uuid::time_mid, and uuid_unpack().

Referenced by add_msg_cb(), append_uuid(), boxc_sent_pop(), boxc_sent_push(), brunet_send_sms(), clickatell_send_sms(), delayed_http_reply(), get_pattern(), kannel_parse_reply(), kannel_send_sms(), main(), main_connection_loop(), status_cb(), store_file_status(), store_spool_save(), store_to_dict(), store_uuid(), and urltrans_fill_escape_codes().

00562 {
00563     struct uuid uuid;
00564 
00565     uuid_unpack(uu, &uuid);
00566     sprintf(out,
00567         "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
00568         uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
00569         uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
00570         uuid.node[0], uuid.node[1], uuid.node[2],
00571         uuid.node[3], uuid.node[4], uuid.node[5]);
00572 }

Here is the call graph for this function:

int uuid_variant const uuid_t  uu  ) 
 

Definition at line 616 of file gw_uuid.c.

References uuid::clock_seq, and uuid_unpack().

00617 {
00618     struct uuid     uuid;
00619     int         var;
00620 
00621     uuid_unpack(uu, &uuid); 
00622     var = uuid.clock_seq;
00623 
00624     if ((var & 0x8000) == 0)
00625         return UUID_VARIANT_NCS;
00626     if ((var & 0x4000) == 0)
00627         return UUID_VARIANT_DCE;
00628     if ((var & 0x2000) == 0)
00629         return UUID_VARIANT_MICROSOFT;
00630     return UUID_VARIANT_OTHER;
00631 }

Here is the call graph for this function:

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.