Skip to content
Snippets Groups Projects
Commit 524c139d authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Add UUID code from John E. Schimmel

parent a5a1fc08
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
/*
* 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 <stdio.h>
#include <sys/types.h>
#ifdef HAVE_SYS_UUID_H
# include <sys/uuid.h>
#else
# include <ac/socket.h>
# include <sys/sockio.h>
# include <net/if_types.h>
# include <net/if.h>
# include <net/if_dl.h>
# ifdef HAVE_SYS_SYSCTL_H
# include <sys/sysctl.h>
# include <net/route.h>
# 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment