xref: /netbsd-src/external/bsd/openldap/dist/libraries/liblutil/uuid.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: uuid.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
24e6df137Slukem 
32de962bdSlukem /* uuid.c -- Universally Unique Identifier routines */
4d11b170bStron /* $OpenLDAP$ */
52de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
62de962bdSlukem  *
7*549b59edSchristos  * Copyright 2000-2021 The OpenLDAP Foundation.
82de962bdSlukem  * Portions Copyright 2000-2003 Kurt D. Zeilenga.
92de962bdSlukem  * All rights reserved.
102de962bdSlukem  *
112de962bdSlukem  * Redistribution and use in source and binary forms, with or without
122de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
132de962bdSlukem  * Public License.
142de962bdSlukem  *
152de962bdSlukem  * A copy of this license is available in the file LICENSE in the
162de962bdSlukem  * top-level directory of the distribution or, alternatively, at
172de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
182de962bdSlukem  */
192de962bdSlukem /* Portions Copyright 2000, John E. Schimmel, All rights reserved.
202de962bdSlukem  * This software is not subject to any license of Mirapoint, Inc.
212de962bdSlukem  *
222de962bdSlukem  * This is free software; you can redistribute and use it
232de962bdSlukem  * under the same terms as OpenLDAP itself.
242de962bdSlukem  */
252de962bdSlukem /* This work was initially developed by John E. Schimmel and adapted
262de962bdSlukem  * for inclusion in OpenLDAP Software by Kurt D. Zeilenga.
272de962bdSlukem  */
282de962bdSlukem 
292de962bdSlukem /*
302de962bdSlukem  * Sorry this file is so scary, but it needs to run on a wide range of
312de962bdSlukem  * platforms.  The only exported routine is lutil_uuidstr() which is all
322de962bdSlukem  * that LDAP cares about.  It generates a new uuid and returns it in
332de962bdSlukem  * in string form.
342de962bdSlukem  */
35376af7d7Schristos #include <sys/cdefs.h>
36*549b59edSchristos __RCSID("$NetBSD: uuid.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
37376af7d7Schristos 
382de962bdSlukem #include "portable.h"
392de962bdSlukem 
402de962bdSlukem #include <limits.h>
412de962bdSlukem #include <stdio.h>
422de962bdSlukem #include <sys/types.h>
432de962bdSlukem 
442de962bdSlukem #include <ac/stdlib.h>
452de962bdSlukem #include <ac/string.h>	/* get memcmp() */
462de962bdSlukem 
472de962bdSlukem #ifdef HAVE_UUID_TO_STR
482de962bdSlukem #  include <sys/uuid.h>
492de962bdSlukem #elif defined( HAVE_UUID_GENERATE )
502de962bdSlukem #  include <uuid/uuid.h>
512de962bdSlukem #elif defined( _WIN32 )
522de962bdSlukem #  include <rpc.h>
532de962bdSlukem #else
542de962bdSlukem #  include <ac/socket.h>
552de962bdSlukem #  include <ac/time.h>
562de962bdSlukem #  ifdef HAVE_SYS_SYSCTL_H
572de962bdSlukem #    include <net/if.h>
582de962bdSlukem #    include <sys/sysctl.h>
592de962bdSlukem #    include <net/route.h>
602de962bdSlukem #  endif
612de962bdSlukem #endif
622de962bdSlukem 
632de962bdSlukem #include <lutil.h>
642de962bdSlukem 
652de962bdSlukem /* not needed for Windows */
662de962bdSlukem #if !defined(HAVE_UUID_TO_STR) && !defined(HAVE_UUID_GENERATE) && !defined(_WIN32)
672de962bdSlukem static unsigned char *
lutil_eaddr(void)682de962bdSlukem lutil_eaddr( void )
692de962bdSlukem {
702de962bdSlukem 	static unsigned char zero[6];
712de962bdSlukem 	static unsigned char eaddr[6];
722de962bdSlukem 
732de962bdSlukem #ifdef HAVE_SYS_SYSCTL_H
742de962bdSlukem 	size_t needed;
752de962bdSlukem 	int mib[6];
762de962bdSlukem 	char *buf, *next, *lim;
772de962bdSlukem 	struct if_msghdr *ifm;
782de962bdSlukem 	struct sockaddr_dl *sdl;
792de962bdSlukem 
802de962bdSlukem 	if (memcmp(eaddr, zero, sizeof(eaddr))) {
812de962bdSlukem 		return eaddr;
822de962bdSlukem 	}
832de962bdSlukem 
842de962bdSlukem 	mib[0] = CTL_NET;
852de962bdSlukem 	mib[1] = PF_ROUTE;
862de962bdSlukem 	mib[3] = 0;
872de962bdSlukem 	mib[3] = 0;
882de962bdSlukem 	mib[4] = NET_RT_IFLIST;
892de962bdSlukem 	mib[5] = 0;
902de962bdSlukem 
912de962bdSlukem 	if (sysctl(mib, sizeof(mib), NULL, &needed, NULL, 0) < 0) {
922de962bdSlukem 		return NULL;
932de962bdSlukem 	}
942de962bdSlukem 
952de962bdSlukem 	buf = malloc(needed);
962de962bdSlukem 	if( buf == NULL ) return NULL;
972de962bdSlukem 
982de962bdSlukem 	if (sysctl(mib, sizeof(mib), buf, &needed, NULL, 0) < 0) {
992de962bdSlukem 		free(buf);
1002de962bdSlukem 		return NULL;
1012de962bdSlukem 	}
1022de962bdSlukem 
1032de962bdSlukem 	lim = buf + needed;
1042de962bdSlukem 	for (next = buf; next < lim; next += ifm->ifm_msglen) {
1052de962bdSlukem 		ifm = (struct if_msghdr *)next;
1062de962bdSlukem 		sdl = (struct sockaddr_dl *)(ifm + 1);
1072de962bdSlukem 
1082de962bdSlukem 		if ( sdl->sdl_family != AF_LINK || sdl->sdl_alen == 6 ) {
1092de962bdSlukem 			AC_MEMCPY(eaddr,
1102de962bdSlukem 				(unsigned char *)sdl->sdl_data + sdl->sdl_nlen,
1112de962bdSlukem 				sizeof(eaddr));
1122de962bdSlukem 			free(buf);
1132de962bdSlukem 			return eaddr;
1142de962bdSlukem 		}
1152de962bdSlukem 	}
1162de962bdSlukem 
1172de962bdSlukem 	free(buf);
1182de962bdSlukem 	return NULL;
1192de962bdSlukem 
1202de962bdSlukem #elif defined( SIOCGIFADDR ) && defined( AFLINK )
1212de962bdSlukem 	char buf[sizeof(struct ifreq) * 32];
1222de962bdSlukem 	struct ifconf ifc;
1232de962bdSlukem 	struct ifreq *ifr;
1242de962bdSlukem 	struct sockaddr *sa;
1252de962bdSlukem 	struct sockaddr_dl *sdl;
1262de962bdSlukem 	unsigned char *p;
1272de962bdSlukem 	int s, i;
1282de962bdSlukem 
1292de962bdSlukem 	if (memcmp(eaddr, zero, sizeof(eaddr))) {
1302de962bdSlukem 		return eaddr;
1312de962bdSlukem 	}
1322de962bdSlukem 
1332de962bdSlukem 	s = socket( AF_INET, SOCK_DGRAM, 0 );
1342de962bdSlukem 	if ( s < 0 ) {
1352de962bdSlukem 		return NULL;
1362de962bdSlukem 	}
1372de962bdSlukem 
1382de962bdSlukem 	ifc.ifc_len = sizeof( buf );
1392de962bdSlukem 	ifc.ifc_buf = buf;
1402de962bdSlukem 	memset( buf, 0, sizeof( buf ) );
1412de962bdSlukem 
1422de962bdSlukem 	i = ioctl( s, SIOCGIFCONF, (char *)&ifc );
1432de962bdSlukem 	close( s );
1442de962bdSlukem 
1452de962bdSlukem 	if( i < 0 ) {
1462de962bdSlukem 		return NULL;
1472de962bdSlukem 	}
1482de962bdSlukem 
1492de962bdSlukem 	for ( i = 0; i < ifc.ifc_len; ) {
1502de962bdSlukem 		ifr = (struct ifreq *)&ifc.ifc_buf[i];
1512de962bdSlukem 		sa = &ifr->ifr_addr;
1522de962bdSlukem 
1532de962bdSlukem 		if ( sa->sa_len > sizeof( ifr->ifr_addr ) ) {
1542de962bdSlukem 			i += sizeof( ifr->ifr_name ) + sa->sa_len;
1552de962bdSlukem 		} else {
1562de962bdSlukem 			i += sizeof( *ifr );
1572de962bdSlukem 		}
1582de962bdSlukem 
1592de962bdSlukem 		if ( sa->sa_family != AF_LINK ) {
1602de962bdSlukem 			continue;
1612de962bdSlukem 		}
1622de962bdSlukem 
1632de962bdSlukem 		sdl = (struct sockaddr_dl *)sa;
1642de962bdSlukem 
1652de962bdSlukem 		if ( sdl->sdl_alen == 6 ) {
1662de962bdSlukem 			AC_MEMCPY(eaddr,
1672de962bdSlukem 				(unsigned char *)sdl->sdl_data + sdl->sdl_nlen,
1682de962bdSlukem 				sizeof(eaddr));
1692de962bdSlukem 			return eaddr;
1702de962bdSlukem 		}
1712de962bdSlukem 	}
1722de962bdSlukem 
1732de962bdSlukem 	return NULL;
1742de962bdSlukem 
1752de962bdSlukem #else
1762de962bdSlukem 	if (memcmp(eaddr, zero, sizeof(eaddr)) == 0) {
1772de962bdSlukem 		/* XXX - who knows? */
1782de962bdSlukem 		lutil_entropy( eaddr, sizeof(eaddr) );
1792de962bdSlukem 		eaddr[0] |= 0x01; /* turn it into a multicast address */
1802de962bdSlukem 	}
1812de962bdSlukem 
1822de962bdSlukem 	return eaddr;
1832de962bdSlukem #endif
1842de962bdSlukem }
1852de962bdSlukem 
1862de962bdSlukem #if (ULONG_MAX >> 31 >> 31) > 1 || defined HAVE_LONG_LONG
1872de962bdSlukem 
1882de962bdSlukem #if (ULONG_MAX >> 31 >> 31) > 1
1892de962bdSlukem     typedef unsigned long       UI64;
1902de962bdSlukem 	/* 100 usec intervals from 10/10/1582 to 1/1/1970 */
1912de962bdSlukem #   define UUID_TPLUS           0x01B21DD2138140ul
1922de962bdSlukem #else
1932de962bdSlukem     typedef unsigned long long  UI64;
1942de962bdSlukem #   define UUID_TPLUS           0x01B21DD2138140ull
1952de962bdSlukem #endif
1962de962bdSlukem 
1972de962bdSlukem #define high32(i)           ((unsigned long) ((i) >> 32))
1982de962bdSlukem #define low32(i)            ((unsigned long) (i) & 0xFFFFFFFFul)
1992de962bdSlukem #define set_add64(res, i)   ((res) += (i))
2002de962bdSlukem #define set_add64l(res, i)  ((res) += (i))
2012de962bdSlukem #define mul64ll(i1, i2)     ((UI64) (i1) * (i2))
2022de962bdSlukem 
2032de962bdSlukem #else /* ! (ULONG_MAX >= 64 bits || HAVE_LONG_LONG) */
2042de962bdSlukem 
2052de962bdSlukem typedef struct {
2062de962bdSlukem 	unsigned long high, low;
2072de962bdSlukem } UI64;
2082de962bdSlukem 
2092de962bdSlukem static const UI64 UUID_TPLUS = { 0x01B21Dul, 0xD2138140ul };
2102de962bdSlukem 
2112de962bdSlukem #define high32(i)			 ((i).high)
2122de962bdSlukem #define low32(i)			 ((i).low)
2132de962bdSlukem 
2142de962bdSlukem /* res += ui64 */
2152de962bdSlukem #define set_add64(res, ui64) \
2162de962bdSlukem { \
2172de962bdSlukem 	res.high += ui64.high; \
2182de962bdSlukem 	res.low	 = (res.low + ui64.low) & 0xFFFFFFFFul; \
2192de962bdSlukem 	if (res.low < ui64.low) res.high++; \
2202de962bdSlukem }
2212de962bdSlukem 
2222de962bdSlukem /* res += ul32 */
2232de962bdSlukem #define set_add64l(res, ul32) \
2242de962bdSlukem { \
2252de962bdSlukem 	res.low	= (res.low + ul32) & 0xFFFFFFFFul; \
2262de962bdSlukem 	if (res.low < ul32) res.high++; \
2272de962bdSlukem }
2282de962bdSlukem 
2292de962bdSlukem /* compute i1 * i2 */
2302de962bdSlukem static UI64
mul64ll(unsigned long i1,unsigned long i2)2312de962bdSlukem mul64ll(unsigned long i1, unsigned long i2)
2322de962bdSlukem {
2332de962bdSlukem 	const unsigned int high1 = (i1 >> 16), low1 = (i1 & 0xffff);
2342de962bdSlukem 	const unsigned int high2 = (i2 >> 16), low2 = (i2 & 0xffff);
2352de962bdSlukem 
2362de962bdSlukem 	UI64 res;
2372de962bdSlukem 	unsigned long tmp;
2382de962bdSlukem 
2392de962bdSlukem 	res.high = (unsigned long) high1 * high2;
2402de962bdSlukem 	res.low	 = (unsigned long) low1	 * low2;
2412de962bdSlukem 
2422de962bdSlukem 	tmp = (unsigned long) low1 * high2;
2432de962bdSlukem 	res.high += (tmp >> 16);
2442de962bdSlukem 	tmp = (tmp << 16) & 0xFFFFFFFFul;
2452de962bdSlukem 	res.low = (res.low + tmp) & 0xFFFFFFFFul;
2462de962bdSlukem 	if (res.low < tmp)
2472de962bdSlukem 		res.high++;
2482de962bdSlukem 
2492de962bdSlukem 	tmp = (unsigned long) low2 * high1;
2502de962bdSlukem 	res.high += (tmp >> 16);
2512de962bdSlukem 	tmp = (tmp << 16) & 0xFFFFFFFFul;
2522de962bdSlukem 	res.low = (res.low + tmp) & 0xFFFFFFFFul;
2532de962bdSlukem 	if (res.low < tmp)
2542de962bdSlukem 		res.high++;
2552de962bdSlukem 
2562de962bdSlukem 	return res;
2572de962bdSlukem }
2582de962bdSlukem 
2592de962bdSlukem #endif /* ULONG_MAX >= 64 bits || HAVE_LONG_LONG */
2602de962bdSlukem 
2612de962bdSlukem #endif /* !HAVE_UUID_TO_STR && !HAVE_UUID_GENERATE && !_WIN32 */
2622de962bdSlukem 
2632de962bdSlukem /*
2642de962bdSlukem ** All we really care about is an ISO UUID string.  The format of a UUID is:
2652de962bdSlukem **	field			octet		note
2662de962bdSlukem **	time_low		0-3		low field of the timestamp
2672de962bdSlukem **	time_mid		4-5		middle field of timestamp
2682de962bdSlukem **	time_hi_and_version	6-7		high field of timestamp and
2692de962bdSlukem **						version number
2702de962bdSlukem **	clock_seq_hi_and_resv	8		high field of clock sequence
2712de962bdSlukem **						and variant
2722de962bdSlukem **	clock_seq_low		9		low field of clock sequence
2732de962bdSlukem **	node			10-15		spacially unique identifier
2742de962bdSlukem **
2752de962bdSlukem ** We use DCE version one, and the DCE variant.  Our unique identifier is
2762de962bdSlukem ** the first ethernet address on the system.
2772de962bdSlukem */
2782de962bdSlukem size_t
lutil_uuidstr(char * buf,size_t len)2792de962bdSlukem lutil_uuidstr( char *buf, size_t len )
2802de962bdSlukem {
2812de962bdSlukem #ifdef HAVE_UUID_TO_STR
2822de962bdSlukem 	uuid_t uu = {0};
2832de962bdSlukem 	unsigned rc;
2842de962bdSlukem 	char *s;
2852de962bdSlukem 	size_t l;
2862de962bdSlukem 
2872de962bdSlukem 	uuid_create( &uu, &rc );
2882de962bdSlukem 	if ( rc != uuid_s_ok ) {
2892de962bdSlukem 		return 0;
2902de962bdSlukem 	}
2912de962bdSlukem 
2922de962bdSlukem 	uuid_to_str( &uu, &s, &rc );
2932de962bdSlukem 	if ( rc != uuid_s_ok ) {
2942de962bdSlukem 		return 0;
2952de962bdSlukem 	}
2962de962bdSlukem 
2972de962bdSlukem 	l = strlen( s );
2982de962bdSlukem 	if ( l >= len ) {
2992de962bdSlukem 		free( s );
3002de962bdSlukem 		return 0;
3012de962bdSlukem 	}
3022de962bdSlukem 
3032de962bdSlukem 	strncpy( buf, s, len );
3042de962bdSlukem 	free( s );
3052de962bdSlukem 
3062de962bdSlukem 	return l;
3072de962bdSlukem 
3082de962bdSlukem #elif defined( HAVE_UUID_GENERATE )
3092de962bdSlukem 	uuid_t uu;
3102de962bdSlukem 
3112de962bdSlukem 	uuid_generate( uu );
3122de962bdSlukem 	uuid_unparse_lower( uu, buf );
3132de962bdSlukem 	return strlen( buf );
3142de962bdSlukem 
3152de962bdSlukem #elif defined( _WIN32 )
3162de962bdSlukem 	UUID uuid;
3172de962bdSlukem 	unsigned char *uuidstr;
3182de962bdSlukem 	size_t uuidlen;
3192de962bdSlukem 
3202de962bdSlukem 	if( UuidCreate( &uuid ) != RPC_S_OK ) {
3212de962bdSlukem 		return 0;
3222de962bdSlukem 	}
3232de962bdSlukem 
3242de962bdSlukem 	if( UuidToString( &uuid, &uuidstr ) !=  RPC_S_OK ) {
3252de962bdSlukem 		return 0;
3262de962bdSlukem 	}
3272de962bdSlukem 
3282de962bdSlukem 	uuidlen = strlen( uuidstr );
3292de962bdSlukem 	if( uuidlen >= len ) {
3302de962bdSlukem 		return 0;
3312de962bdSlukem 	}
3322de962bdSlukem 
3332de962bdSlukem 	strncpy( buf, uuidstr, len );
3342de962bdSlukem 	RpcStringFree( &uuidstr );
3352de962bdSlukem 
3362de962bdSlukem 	return uuidlen;
3372de962bdSlukem 
3382de962bdSlukem #else
3392de962bdSlukem 	struct timeval tv;
3402de962bdSlukem 	UI64 tl;
3412de962bdSlukem 	unsigned char *nl;
3422de962bdSlukem 	unsigned short t2, t3, s1;
3432de962bdSlukem 	unsigned long t1, tl_high;
3442de962bdSlukem 	unsigned int rc;
3452de962bdSlukem 
3462de962bdSlukem 	/*
3472de962bdSlukem 	 * Theoretically we should delay if seq wraps within 100usec but for now
3482de962bdSlukem 	 * systems are not fast enough to worry about it.
3492de962bdSlukem 	 */
3502de962bdSlukem 	static int inited = 0;
3512de962bdSlukem 	static unsigned short seq;
3522de962bdSlukem 
3532de962bdSlukem 	if (!inited) {
3542de962bdSlukem 		lutil_entropy( (unsigned char *) &seq, sizeof(seq) );
3552de962bdSlukem 		inited++;
3562de962bdSlukem 	}
3572de962bdSlukem 
3582de962bdSlukem #ifdef HAVE_GETTIMEOFDAY
3592de962bdSlukem 	gettimeofday( &tv, 0 );
3602de962bdSlukem #else
3612de962bdSlukem 	time( &tv.tv_sec );
3622de962bdSlukem 	tv.tv_usec = 0;
3632de962bdSlukem #endif
3642de962bdSlukem 
3652de962bdSlukem 	tl = mul64ll(tv.tv_sec, 10000000UL);
3662de962bdSlukem 	set_add64l(tl, tv.tv_usec * 10UL);
3672de962bdSlukem 	set_add64(tl, UUID_TPLUS);
3682de962bdSlukem 
3692de962bdSlukem 	nl = lutil_eaddr();
3702de962bdSlukem 
3712de962bdSlukem 	t1 = low32(tl);				/* time_low */
3722de962bdSlukem 	tl_high = high32(tl);
3732de962bdSlukem 	t2 = tl_high & 0xffff;		/* time_mid */
3742de962bdSlukem 	t3 = ((tl_high >> 16) & 0x0fff) | 0x1000;	/* time_hi_and_version */
3752de962bdSlukem 	s1 = ( ++seq & 0x1fff ) | 0x8000;		/* clock_seq_and_reserved */
3762de962bdSlukem 
3772de962bdSlukem 	rc = snprintf( buf, len,
3782de962bdSlukem 		"%08lx-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
3792de962bdSlukem 		t1, (unsigned) t2, (unsigned) t3, (unsigned) s1,
3802de962bdSlukem 		(unsigned) nl[0], (unsigned) nl[1],
3812de962bdSlukem 		(unsigned) nl[2], (unsigned) nl[3],
3822de962bdSlukem 		(unsigned) nl[4], (unsigned) nl[5] );
3832de962bdSlukem 
3842de962bdSlukem 	return rc < len ? rc : 0;
3852de962bdSlukem #endif
3862de962bdSlukem }
3872de962bdSlukem 
3882de962bdSlukem int
lutil_uuidstr_from_normalized(char * uuid,size_t uuidlen,char * buf,size_t buflen)3892de962bdSlukem lutil_uuidstr_from_normalized(
3902de962bdSlukem 	char		*uuid,
3912de962bdSlukem 	size_t		uuidlen,
3922de962bdSlukem 	char		*buf,
3932de962bdSlukem 	size_t		buflen )
3942de962bdSlukem {
3952de962bdSlukem 	unsigned char nibble;
3962de962bdSlukem 	int i, d = 0;
3972de962bdSlukem 
3982de962bdSlukem 	assert( uuid != NULL );
3992de962bdSlukem 	assert( buf != NULL );
4002de962bdSlukem 
4012de962bdSlukem 	if ( uuidlen != 16 ) return -1;
4022de962bdSlukem 	if ( buflen < 36 ) return -1;
4032de962bdSlukem 
4042de962bdSlukem 	for ( i = 0; i < 16; i++ ) {
4052de962bdSlukem 		if ( i == 4 || i == 6 || i == 8 || i == 10 ) {
4062de962bdSlukem 			buf[(i<<1)+d] = '-';
4072de962bdSlukem 			d += 1;
4082de962bdSlukem 		}
4092de962bdSlukem 
4102de962bdSlukem 		nibble = (uuid[i] >> 4) & 0xF;
4112de962bdSlukem 		if ( nibble < 10 ) {
4122de962bdSlukem 			buf[(i<<1)+d] = nibble + '0';
4132de962bdSlukem 		} else {
4142de962bdSlukem 			buf[(i<<1)+d] = nibble - 10 + 'a';
4152de962bdSlukem 		}
4162de962bdSlukem 
4172de962bdSlukem 		nibble = (uuid[i]) & 0xF;
4182de962bdSlukem 		if ( nibble < 10 ) {
4192de962bdSlukem 			buf[(i<<1)+d+1] = nibble + '0';
4202de962bdSlukem 		} else {
4212de962bdSlukem 			buf[(i<<1)+d+1] = nibble - 10 + 'a';
4222de962bdSlukem 		}
4232de962bdSlukem 	}
4242de962bdSlukem 
4252de962bdSlukem 	if ( buflen > 36 ) buf[36] = '\0';
4262de962bdSlukem 	return 36;
4272de962bdSlukem }
4282de962bdSlukem 
4292de962bdSlukem #ifdef TEST
4302de962bdSlukem int
main(int argc,char ** argv)4312de962bdSlukem main(int argc, char **argv)
4322de962bdSlukem {
4332de962bdSlukem 	char buf1[8], buf2[64];
4342de962bdSlukem 
4352de962bdSlukem #ifndef HAVE_UUID_TO_STR
4362de962bdSlukem 	unsigned char *p = lutil_eaddr();
4372de962bdSlukem 
4382de962bdSlukem 	if( p ) {
4392de962bdSlukem 		printf( "Ethernet Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
4402de962bdSlukem 			(unsigned) p[0], (unsigned) p[1], (unsigned) p[2],
4412de962bdSlukem 			(unsigned) p[3], (unsigned) p[4], (unsigned) p[5]);
4422de962bdSlukem 	}
4432de962bdSlukem #endif
4442de962bdSlukem 
4452de962bdSlukem 	if ( lutil_uuidstr( buf1, sizeof( buf1 ) ) ) {
4462de962bdSlukem 		printf( "UUID: %s\n", buf1 );
4472de962bdSlukem 	} else {
4482de962bdSlukem 		fprintf( stderr, "too short: %ld\n", (long) sizeof( buf1 ) );
4492de962bdSlukem 	}
4502de962bdSlukem 
4512de962bdSlukem 	if ( lutil_uuidstr( buf2, sizeof( buf2 ) ) ) {
4522de962bdSlukem 		printf( "UUID: %s\n", buf2 );
4532de962bdSlukem 	} else {
4542de962bdSlukem 		fprintf( stderr, "too short: %ld\n", (long) sizeof( buf2 ) );
4552de962bdSlukem 	}
4562de962bdSlukem 
4572de962bdSlukem 	if ( lutil_uuidstr( buf2, sizeof( buf2 ) ) ) {
4582de962bdSlukem 		printf( "UUID: %s\n", buf2 );
4592de962bdSlukem 	} else {
4602de962bdSlukem 		fprintf( stderr, "too short: %ld\n", (long) sizeof( buf2 ) );
4612de962bdSlukem 	}
4622de962bdSlukem 
4632de962bdSlukem 	return 0;
4642de962bdSlukem }
4652de962bdSlukem #endif
466