From 524c139d7c43b15aa34f69605e5c487156255270 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Wed, 5 Dec 2001 05:39:34 +0000 Subject: [PATCH] Add UUID code from John E. Schimmel --- libraries/liblutil/Makefile.in | 4 +- libraries/liblutil/uuid.c | 284 +++++++++++++++++++++++++++++++++ 2 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 libraries/liblutil/uuid.c diff --git a/libraries/liblutil/Makefile.in b/libraries/liblutil/Makefile.in index f40e04c54c..374d893e07 100644 --- a/libraries/liblutil/Makefile.in +++ b/libraries/liblutil/Makefile.in @@ -14,11 +14,11 @@ UNIX_SRCS = detach.c UNIX_OBJS = detach.o SRCS = base64.c debug.c entropy.c sasl.c signal.c hash.c \ - md5.c passwd.c sha1.c getpass.c lockf.c utils.c sockpair.c \ + md5.c passwd.c sha1.c getpass.c lockf.c utils.c uuid.c sockpair.c \ @LIBSRCS@ $(@PLAT@_SRCS) OBJS = base64.o debug.o entropy.o sasl.o signal.o hash.o \ - md5.o passwd.o sha1.o getpass.o lockf.o utils.o sockpair.o \ + md5.o passwd.o sha1.o getpass.o lockf.o utils.o uuid.o sockpair.o \ @LIBOBJS@ $(@PLAT@_OBJS) LDAP_INCDIR= ../../include diff --git a/libraries/liblutil/uuid.c b/libraries/liblutil/uuid.c new file mode 100644 index 0000000000..22dc216b20 --- /dev/null +++ b/libraries/liblutil/uuid.c @@ -0,0 +1,284 @@ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Portions + * Copyright 2000, John E. Schimmel, All rights reserved. + * This software is not subject to any license of Mirapoint, Inc. + * + * This is free software; you can redistribute and use it + * under the same terms as OpenLDAP itself. + */ +/* Adapted for incorporatation into OpenLDAP by Kurt Zeilenga */ + +/* +** Sorry this file is so scary, but it needs to run on a wide range of +** platforms. The only exported routine is lutil_uuidstr() which is all +** that LDAP cares about. It generates a new uuid and returns it in +** in string form. +*/ +#include "portable.h" + +#include +#include + +#ifdef HAVE_SYS_UUID_H +# include +#else +# include +# include +# include +# include +# include +# ifdef HAVE_SYS_SYSCTL_H +# include +# include +# endif +#endif + +/* 100 usec intervals from 10/10/1582 to 1/1/1970 */ +#define UUID_TPLUS 0x01B21DD2138140LL + +#ifndef HAVE_SYS_UUID_H +static unsigned char * +lutil_eaddr( void ) +{ + static unsigned char zero[6]; + static unsigned char eaddr[6]; + +#ifdef HAVE_SYS_SYSCTL_H + size_t needed; + int mib[6]; + char *buf, *next, *lim; + struct if_msghdr *ifm; + struct sockaddr_dl *sdl; + + if (memcmp(eaddr, zero, sizeof(eaddr))) { + return eaddr; + } + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[3] = 0; + mib[3] = 0; + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + + if (sysctl(mib, sizeof(mib), NULL, &needed, NULL, 0) < 0) { + return NULL; + } + + buf = malloc(needed); + if( buf == NULL ) return NULL; + + if (sysctl(mib, sizeof(mib), buf, &needed, NULL, 0) < 0) { + free(buf); + return NULL; + } + + lim = buf + needed; + for (next = buf; next < lim; next += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)next; + sdl = (struct sockaddr_dl *)(ifm + 1); + + if ( sdl->sdl_family != AF_LINK || sdl->sdl_alen == 6 ) { + memcpy(eaddr, + (unsigned char *)sdl->sdl_data + sdl->sdl_nlen, + sizeof(eaddr)); + free(buf); + return eaddr; + } + } + + free(buf); + return NULL; + +#elif defined (SIOCGIFADDR) + char buf[sizeof(struct ifreq) * 32]; + struct ifconf ifc; + struct ifreq *ifr; + struct sockaddr *sa; + struct sockaddr_dl *sdl; + unsigned char *p; + int s, i; + + if (memcmp(eaddr, zero, sizeof(eaddr))) { + return eaddr; + } + + s = socket( AF_INET, SOCK_DGRAM, 0 ); + if ( s < 0 ) { + return NULL; + } + + ifc.ifc_len = sizeof( buf ); + ifc.ifc_buf = buf; + memset( buf, 0, sizeof( buf ) ); + + i = ioctl( s, SIOCGIFCONF, (char *)&ifc ); + close( s ); + + if( i < 0 ) { + return NULL; + } + + for ( i = 0; i < ifc.ifc_len; ) { + ifr = (struct ifreq *)&ifc.ifc_buf[i]; + sa = &ifr->ifr_addr; + + if ( sa->sa_len > sizeof( ifr->ifr_addr ) ) { + i += sizeof( ifr->ifr_name ) + sa->sa_len; + } else { + i += sizeof( *ifr ); + } + + if ( sa->sa_family != AF_LINK ) { + continue; + } + + sdl = (struct sockaddr_dl *)sa; + + if ( sdl->sdl_alen == 6 ) { + memcpy(eaddr, + (unsigned char *)sdl->sdl_data + sdl->sdl_nlen, + sizeof(eaddr)); + return eaddr; + } + } + + return NULL; + +#else + if (memcmp(eaddr, zero, sizeof(eaddr)) == 0) { + /* XXX - who knows? */ + lutil_entropy( eaddr, sizeof(eaddr) ); + } + + return eaddr; +#endif +} +#endif + +/* +** All we really care about is an ISO UUID string. The format of a UUID is: +** field octet note +** time_low 0-3 low field of the timestamp +** time_mid 4-5 middle field of timestamp +** time_hi_and_version 6-7 high field of timestamp and +** version number +** clock_seq_hi_and_resv 8 high field of clock sequence +** and variant +** clock_seq_low 9 low field of clock sequence +** node 10-15 spacially unique identifier +** +** We use DCE version one, and the DCE variant. Our unique identifier is +** the first ethernet address on the system. +*/ +int +lutil_uuidstr( char *buf, size_t len ) +{ +#ifdef HAVE_SYS_UUID_H + uuid_t uu = {0}; + unsigned rc; + char *s; + + uuid_create( &uu, &rc ); + if ( rc != uuid_s_ok ) { + return 0; + } + + uuid_to_str( &uu, &s, &rc ); + if ( rc != uuid_s_ok ) { + return 0; + } + if ( strlen( s ) >= len ) { + free( s ); + return 0; + } + + strncpy( buf, s, len ); + free( s ); + + return 1; + +#else + struct timeval tv; + unsigned long long tl; + unsigned char *nl; + unsigned short sq, t2, t3, s1, n1, n2, n3; + unsigned int t1; + + /* + * Theoretically we should delay if seq wraps within 100usec but for now + * systems are not fast enough to worry about it. + */ + static unsigned short seq = 0; + +#ifdef HAVE_GETTIMEOFDAY + gettimeofday( &tv, 0 ); +#else + time( &tv.tv_sec ); + tv.tv_usec = 0; +#endif + + tl = ( tv.tv_sec * 10000000LL ) + ( tv.tv_usec * 10LL ) + UUID_TPLUS; + nl = lutil_eaddr(); + + if (! seq) { + lutil_entropy( &seq, sizeof(seq) ); + } + sq = ++seq; + + t1 = tl & 0xffffffff; /* time_low */ + t2 = ( tl >> 32 ) & 0xffff; /* time_mid */ + t3 = ( tl >> 48 ) & 0x0fff | 0x1000; /* time_hi_and_version */ + s1 = (sq & 0x1fff ) | 0x8000; /* clock_seq_and_reserved */ + + t1 = snprintf( buf, len, + "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", + t1, (unsigned) t2, (unsigned) t3, (unsigned) s1, + (unsigned) nl[0], (unsigned) nl[1], + (unsigned) nl[2], (unsigned) nl[3], + (unsigned) nl[4], (unsigned) nl[5] ); + + return (t1 < len) ? 1 : 0; +#endif +} + +#ifdef TEST +int +main(int argc, char **argv) +{ + char buf1[8], buf2[64]; + +#ifndef HAVE_SYS_UUID_H + unsigned char *p = lutil_eaddr(); + + if( p ) { + printf( "Ethernet Address: %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned) p[0], (unsigned) p[1], (unsigned) p[2], + (unsigned) p[3], (unsigned) p[4], (unsigned) p[5]); + } +#endif + + if ( lutil_uuidstr( buf1, sizeof( buf1 ) ) ) { + printf( "UUID: %s\n", buf1 ); + } else { + fprintf( stderr, "too short: %ld\n", (long) sizeof( buf1 ) ); + } + + if ( lutil_uuidstr( buf2, sizeof( buf2 ) ) ) { + printf( "UUID: %s\n", buf2 ); + } else { + fprintf( stderr, "too short: %ld\n", (long) sizeof( buf2 ) ); + } + + if ( lutil_uuidstr( buf2, sizeof( buf2 ) ) ) { + printf( "UUID: %s\n", buf2 ); + } else { + fprintf( stderr, "too short: %ld\n", (long) sizeof( buf2 ) ); + } + + return 0; +} +#endif -- 2.39.5