#include "niml_private.h"
/*************************************************************************/
/***************** Unique Identifier String functions ********************/
/*************************************************************************/
#include <sys/utsname.h> /* Need by UNIQ_ functions for uname() */
#include <time.h>
static char *get_MAC_addr(void) ; /* prototype */
/*-----------------------------------------------------------------------*/
/*! Return a globally unique string (I hope). This can be hashed to
produce a unique idcode (cf. UNIQ_idcode and UUID_idcode).
Method: Generate a string from the system identfier information and
the current time of day. The output string is malloc()-ed,
and should be free()-ed when no longer needed.
20 Aug 2002 -- RWCox: break string and hashing into separate functions.
-------------------------------------------------------------------------*/
static char * get_UNIQ_string(void)
{
static struct utsname ubuf ;
static int ncall=0 ; /* number of times I've been called */
struct timeval tv ;
int nn , ii ;
int nbuf ;
char *buf ;
#define NURR 32 /* # bytes from /dev/urandom at a time */
#ifdef NURR
static int nurr=0 ;
static byte urr[NURR] ; /* will use 1 byte from urr[nurr] */
#endif
/* get info about this system */
if( ncall == 0 ){ /* 21 Aug 2002: only 1st time in */
nn = uname( &ubuf ) ; /* get info about this system */
if( nn == -1 ){ /* should never happen */
strcpy( ubuf.nodename , "E" ) ;
strcpy( ubuf.sysname , "L" ) ;
strcpy( ubuf.release , "V" ) ;
strcpy( ubuf.version , "I" ) ;
strcpy( ubuf.machine , "S" ) ;
}
}
/* store system info into a string buffer */
nbuf = strlen(ubuf.nodename)+strlen(ubuf.sysname)
+strlen(ubuf.release )+strlen(ubuf.version)+strlen(ubuf.machine) ;
buf = (char *)malloc(nbuf+222) ; /* include some extra space */
strcpy(buf,ubuf.nodename) ;
strcat(buf,ubuf.sysname ) ;
strcat(buf,ubuf.release ) ;
strcat(buf,ubuf.version ) ;
strcat(buf,ubuf.machine ) ;
/* get time and store into buf (along with process+user id and ncall) */
nn = gettimeofday( &tv , NULL ) ;
if( nn == -1 ){ /* should never happen */
tv.tv_sec = (long) time(NULL) ; /* get seconds another way */
tv.tv_usec = (long) buf ; /* address as an integer */
}
/* even if called twice in very rapid succession,
at least ncall will differ, so we'll get different ID codes */
sprintf( buf+nbuf,"%d%d%d%d%d%d",
(int)tv.tv_sec,(int)tv.tv_usec,
(int)getpid(),(int)getppid(),(int)getuid(),
ncall ) ;
ncall++ ;
/* 06 Jan 2003: append MAC address, if possible */
strcat(buf,get_MAC_addr()) ;
#ifdef NURR
/* 24 Jul 2002: get random bytes from /dev/urandom */
/* 21 Aug 2002: read NURR bytes at a time, but only use 1 per call */
if( nurr >= 0 ){
if( nurr == 0 ){ /* need to read more bytes */
FILE *ufp=fopen("/dev/urandom","rb") ;
if( ufp == NULL ){ /* fails on open */
nurr = -1; goto URR_DONE; /* so never try again */
} else { /* read some bytes */
fread( &urr , 1,NURR, ufp ); fclose(ufp);
}
}
nbuf = strlen(buf); sprintf(buf+nbuf,"%02x",(int)urr[nurr]);
nurr = (nurr+1) % NURR ;
URR_DONE: ;
}
#endif /* NURR */
return buf ;
}
/*-----------------------------------------------------------------------*/
/*! Return a globally unique identifier (I hope). This is a malloc()-ed
string of length <= 31 (plus the NUL byte; the whole thing will fit
into a char[32] array). The output does not contain any '/'s, so
it could be used as a temporary filename. Repeated calls to this
function should never return the same string.
Method: Generate a string from the system identfier information and
the current time of day. MD5 hash this to a 128 byte code.
Base64 encode this to a 22 byte string. Replace '/' with '-'
and '+' with '_'. Add 4 character prefix (1st 3 characters
of environment variable IDCODE_PREFIX plus '_').
Sample output: "XYZ_VdfGpfzy_NlY-2d7tA8Q1w"
-------------------------------------------------------------------------*/
char * UNIQ_idcode(void)
{
char *buf , *idc ;
/* get uniq string from system */
buf = get_UNIQ_string() ;
/* make the output by hashing the string in buf */
idc = UNIQ_hashcode( buf ) ;
/* free workspace and get outta here */
free(buf) ; return idc ;
}
/*----------------------------------------------------------------------*/
/*! Make an idcode-formatted malloc-ed string from an input string.
Unlike UNIQ_idcode(), this will always return the same value,
given the same input.
------------------------------------------------------------------------*/
char * UNIQ_hashcode( char *str )
{
char *idc , *eee ;
int ii , nn ;
idc = (char *)calloc(1,32) ;
eee = getenv("IDCODE_PREFIX") ;
if( eee != NULL && isalpha(eee[0]) ){
for( ii=0 ; ii < 3 && isalnum(eee[ii]) ; ii++ )
idc[ii] = eee[ii] ;
} else {
strcpy(idc,"XYZ") ; /* innocent default prefix */
}
strcat(idc,"_") ; /* recall idc was calloc()-ed */
if( str == NULL || str[0] == '\0' ) str = "Onen i Estel Edain" ;
eee = MD5_B64_string(str) ;
nn = strlen(eee) ;
for( ii=0 ; ii < nn ; ii++ ){
if( eee[ii] == '/' ) eee[ii] = '-' ; /* / -> - */
else if( eee[ii] == '+' ) eee[ii] = '_' ; /* + -> _ */
}
strcat(idc,eee) ; free(eee) ; return idc ;
}
/*----------------------------------------------------------------------*/
/*! Fill a user-supplied buffer (length at least 32) with an idcode.
That is, idc should point to a char array of length 32 (or more).
------------------------------------------------------------------------*/
void UNIQ_idcode_fill( char *idc )
{
char *bbb ;
if( idc == NULL ) return ;
bbb = UNIQ_idcode() ;
strcpy(idc,bbb) ; free(bbb) ; return ;
}
/*----------------------------------------------------------------------*/
/*! Hash a string and return a malloc()-ed string (36+1 bytes) in
the "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" format.
------------------------------------------------------------------------*/
char *UUID_hashcode( char *str )
{
MD5_CTX context;
unsigned char digest[16];
char *idc ;
int ii , nn ;
if( str == NULL || str[0] == '\0' ) str = "Onen i Estel Edain" ;
MD5Init( &context ) ;
MD5Update( &context, (unsigned char *)str, strlen(str) ) ;
MD5Final( digest, &context ) ;
idc = (char *)calloc(1,48) ;
sprintf(idc,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" ,
digest[0] , digest[1] , digest[2] , digest[3] , digest[4] ,
digest[5] , digest[6] , digest[7] , digest[8] , digest[9] ,
digest[10], digest[11], digest[12], digest[13], digest[14],
digest[15]
) ;
return idc ;
}
/*----------------------------------------------------------------------*/
/*! Hash a unique string and return a malloc()-ed string (36+1 bytes) in
the "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" format.
The result should be unique worldwide, for all time.
------------------------------------------------------------------------*/
char * UUID_idcode(void)
{
char *buf , *idc ;
/* get uniq string from system */
buf = get_UNIQ_string() ;
/* make the output by hashing the string in buf */
idc = UUID_hashcode( buf ) ;
/* free workspace and get outta here */
free(buf) ; return idc ;
}
/************************************************************************/
#include <sys/ioctl.h>
#include <net/if.h>
static char *get_MAC_addr(void) /* 06 Jan 2003 */
{
static char str[64] = "?" ;
#if defined(LINUX) && defined(SIOCGIFHWADDR)
static int ncall=0 ;
if( ncall == 0 ){
int sd ;
sd = socket(AF_INET, SOCK_DGRAM, 0);
if( sd >= 0 ){
struct ifreq ifr ;
strcpy(ifr.ifr_name, "eth0") ;
if( ioctl(sd,SIOCGIFHWADDR,&ifr) >= 0 ){
sprintf(str ,
"%02x:%02x:%02x:%02x:%02x:%02x",
(byte)ifr.ifr_hwaddr.sa_data[0], (byte)ifr.ifr_hwaddr.sa_data[1],
(byte)ifr.ifr_hwaddr.sa_data[2], (byte)ifr.ifr_hwaddr.sa_data[3],
(byte)ifr.ifr_hwaddr.sa_data[4], (byte)ifr.ifr_hwaddr.sa_data[5] ) ;
}
close(sd) ;
}
ncall = 1 ;
}
#endif
return str ;
}
syntax highlighted by Code2HTML, v. 0.9.1