Commit 6709a311 authored by Pekka Pessi's avatar Pekka Pessi

Updated globally unique identifier (uuid) generation.

Using getifaddrs() and /dev/urandom. Added checks for /dev/urandom
and <netpacket/packet.h> (for link-level addresses).

darcs-hash:20060309134200-65a35-9e12a1e1dfad1609d45c66ea22e053f3f244893d.gz
parent 5d9d9e1d
......@@ -27,8 +27,8 @@ SAC_ENABLE_EXPENSIVE_CHECKS
AC_GNU_SOURCE
dnl checks for programs
dnl -------------------
### checks for programs
### -------------------
AC_CHECK_COMPILATION_ENVIRONMENT
AX_TOOL_CC
......@@ -86,6 +86,7 @@ AC_DEFINE([HAVE_UPNP], 0, [Define as 1 if we use UPnP])
### checks for header files
### -----------------------
AC_HEADER_STDC
### checks for declarations
### -----------------------
......@@ -106,10 +107,6 @@ AC_DEFINE([LLX], ["%llx"], [Define as format (%llx) for long long hex])dnl
### checks for structures
### ---------------------
AC_HEADER_STDC
dnl AC_CHECK_HEADERS(pthread.h)
dnl AC_CHECK_HEADERS(stdint.h)
dnl AC_CHECK_HEADERS(inttypes.h)
### checks for typedefs, structures, and compiler characteristics.
### --------------------------------------------------------------
......@@ -130,16 +127,11 @@ AC_SYS_SA_LEN
### checks for library functions
### ----------------------------
AC_SEARCH_LIBS(gethostbyname, xnet nsl)
AC_SEARCH_LIBS(getipnodebyname, xnet socket nsl)
AC_SEARCH_LIBS(getaddrinfo, xnet socket nsl)
AC_SEARCH_LIBS(socket, xnet socket)
AC_SEARCH_LIBS(inet_ntop, socket nsl)
AC_SEARCH_LIBS(inet_pton, socket nsl)
### checks for system services
### --------------------------
dnl XXX
AC_DEV_URANDOM
### output
### ------
......
......@@ -56,6 +56,9 @@ typedef union GloballyUniqueIdentifier {
} s;
} su_guid_t;
/** Return node identifier */
size_t su_node_identifier(void *address, size_t addrlen);
/** Generate a GUID
*
* The function guid_generate() generates a new globally unique identifier
......
......@@ -73,6 +73,7 @@ int _getpid(void);
static int initialized = 0;
static void init(void);
static void init_node(void);
/* Constants */
static const unsigned version = 1; /* Current version */
......@@ -90,6 +91,8 @@ static uint64_t timestamp0 = 0;
static unsigned clock_sequence = MAGIC;
static unsigned char node[6];
FILE *urandom;
/*
* Get current timestamp
*/
......@@ -109,10 +112,8 @@ static uint64_t timestamp(void)
tl &= mask60;
if (tl <= timestamp0) {
clock_sequence++;
clock_sequence &= MAGIC - 1;
}
if (tl <= timestamp0)
clock_sequence = (clock_sequence + 1) & (MAGIC - 1);
timestamp0 = tl;
......@@ -137,18 +138,28 @@ static void init(void)
initialized = 1;
/* Initialize our random number generator */
for (i = 0; i < 16; i++) {
#if HAVE_DEV_URANDOM
if (!urandom)
urandom = fopen("/dev/urandom", "rb");
#endif /* HAVE_DEV_URANDOM */
if (urandom) {
fread(seed, sizeof seed, 1, urandom);
}
else {
for (i = 0; i < 16; i++) {
#if HAVE_CLOCK_GETTIME
struct timespec ts;
(void)clock_gettime(CLOCK_REALTIME, &ts);
seed[2*i] ^= ts.tv_sec; seed[2*i+1] ^= ts.tv_nsec;
struct timespec ts;
(void)clock_gettime(CLOCK_REALTIME, &ts);
seed[2*i] ^= ts.tv_sec; seed[2*i+1] ^= ts.tv_nsec;
#endif
su_time(&now);
seed[2*i] ^= now.tv_sec; seed[2*i+1] ^= now.tv_sec;
}
su_time(&now);
seed[2*i] ^= now.tv_sec; seed[2*i+1] ^= now.tv_sec;
}
seed[30] ^= getuid();
seed[31] ^= getpid();
seed[30] ^= getuid();
seed[31] ^= getpid();
}
#if HAVE_INITSTATE
initstate(seed[0] ^ seed[1], (char *)&seed, sizeof(seed));
......@@ -160,7 +171,59 @@ static void init(void)
(void)timestamp();
for (i = 0; i < sizeof(node); i++) {
init_node();
}
#if HAVE_GETIFADDRS
#include <ifaddrs.h>
#if HAVE_NETPACKET_PACKET_H
#define HAVE_SOCKADDR_LL
#include <netpacket/packet.h>
#include <net/if_arp.h>
#endif
#endif
static
void init_node(void)
{
int i;
#if HAVE_GETIFADDRS && HAVE_SOCKADDR_LL
struct ifaddrs *ifa, *results;
if (getifaddrs(&results) == 0) {
for (ifa = results; ifa; ifa = ifa->ifa_next) {
#if HAVE_SOCKADDR_LL
struct sockaddr_ll const *sll = (void *)ifa->ifa_addr;
if (sll->sll_family != AF_PACKET)
continue;
switch (sll->sll_hatype) {
case ARPHRD_ETHER:
case ARPHRD_EETHER:
case ARPHRD_IEEE802:
break;
default:
continue;
}
memcpy(node, sll->sll_addr, sizeof node);
break;
#endif
}
freeifaddrs(results);
if (ifa)
return; /* Success */
}
#endif
if (urandom) {
fread(node, sizeof node, 1, urandom);
}
else for (i = 0; i < sizeof(node); i++) {
unsigned r = random();
node[i] = (r >> 24) ^ (r >> 16) ^ (r >> 8) ^ r;
}
......@@ -168,6 +231,18 @@ static void init(void)
node[0] |= 1; /* "multicast" address */
}
size_t su_node_identifier(void *address, size_t addrlen)
{
if (addrlen > sizeof node)
addrlen = sizeof node;
if (!initialized) init();
memcpy(address, node, addrlen);
return addrlen;
}
void su_guid_generate(su_guid_t *v)
{
uint64_t time;
......@@ -190,7 +265,8 @@ void su_guid_generate(su_guid_t *v)
/*
* Human-readable form of GloballyUniqueID
*/
int su_guid_sprintf(char* buf, size_t len, su_guid_t const *v) {
int su_guid_sprintf(char* buf, size_t len, su_guid_t const *v)
{
char mybuf[su_guid_strlen + 1];
sprintf(mybuf, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
(unsigned long)ntohl(v->s.time_low),
......
......@@ -471,3 +471,19 @@ AC_DEFUN([AC_TYPE_LONGLONG],[dnl
AC_CHECK_TYPE([long long],[dnl
AC_DEFINE([longlong], [long long], [Define as at least 64-bit int type])dnl
ifelse([$1], ,:, [$1])],[ifelse([$2], ,:, [$2])])])
dnl ======================================================================
dnl Check for /dev/urandom
dnl ======================================================================
AC_DEFUN([AC_DEV_URANDOM],[
AC_CACHE_CHECK([/dev/urandom], [ac_cv_dev_urandom],
[ac_cv_dev_urandom=no
if test -r /dev/urandom; then ac_cv_dev_urandom=yes; fi])
if test $ac_cv_dev_urandom = yes; then
AC_DEFINE([HAVE_DEV_URANDOM], 1,
[Define this as 1 if you have /dev/urandom.])
AC_DEFINE([DEV_URANDOM], 1,
[Define this as the random number source name.])
fi
])
......@@ -140,7 +140,7 @@ dnl no winsock2
SAC_SU_DEFINE([SU_HAVE_BSDSOCK], 1, [Define as 1 if you have BSD socket interface])
AC_CHECK_HEADERS([sys/socket.h sys/ioctl.h sys/filio.h sys/sockio.h])
AC_CHECK_HEADERS([netinet/in.h arpa/inet.h netdb.h \
net/if.h net/if_types.h ifaddr.h],,,
net/if.h net/if_types.h ifaddr.h netpacket/packet.h],,,
[sys/types.h sys/socket.h])
AC_CACHE_CHECK([for struct addrinfo],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment