* Use our own time-based UUID generation functions, to help eliminate potential compiling issues.

This commit is contained in:
Justin Maggard 2009-09-01 02:54:20 +00:00
parent a78c7c9077
commit 25861ebf92
11 changed files with 332 additions and 91 deletions

View File

@ -1,14 +1,14 @@
# $Id$
# MiniUPnP project
# http://miniupnp.free.fr/
# Author : Thomas Bernard
# MiniDLNA project
# http://sourceforge.net/projects/minidlna/
# (c) 2008-2009 Justin Maggard
# for use with GNU Make
# To install use :
# $ PREFIX=/dummyinstalldir make -f Makefile.linux install
# $ PREFIX=/dummyinstalldir make install
# or :
# $ INSTALLPREFIX=/usr/local make -f Makefile.linux install
# $ INSTALLPREFIX=/usr/local make install
# or :
# $ make -f Makefile.linux install
# $ make install
#
#CFLAGS = -Wall -O -D_GNU_SOURCE -g -DDEBUG
#CFLAGS = -Wall -g -Os -D_GNU_SOURCE
@ -27,7 +27,7 @@ ETCINSTALLDIR = $(PREFIX)/etc
BASEOBJS = minidlna.o upnphttp.o upnpdescgen.o upnpsoap.o \
upnpreplyparse.o minixml.o \
getifaddr.o daemonize.o upnpglobalvars.o \
options.o minissdp.o upnpevents.o \
options.o minissdp.o uuid.o upnpevents.o \
sql.o utils.o metadata.o scanner.o inotify.o \
tivo_utils.o tivo_beacon.o tivo_commands.o \
tagutils/textutils.o tagutils/misc.o tagutils/tagutils.o \
@ -76,8 +76,7 @@ depend: config.h
minidlna.o: config.h upnpglobalvars.h minidlnatypes.h
minidlna.o: upnphttp.h upnpdescgen.h minidlnapath.h getifaddr.h upnpsoap.h
minidlna.o: options.h minissdp.h daemonize.h upnpevents.h
minidlna.o: commonrdr.h log.h
minidlna.o: options.h minissdp.h daemonize.h upnpevents.h log.h
upnphttp.o: config.h upnphttp.h upnpdescgen.h minidlnapath.h upnpsoap.h
upnphttp.o: upnpevents.h image_utils.h sql.h log.h icons.c
upnpdescgen.o: config.h upnpdescgen.h minidlnapath.h upnpglobalvars.h
@ -95,7 +94,8 @@ options.o: minidlnatypes.h
minissdp.o: config.h upnpdescstrings.h minidlnapath.h upnphttp.h
minissdp.o: upnpglobalvars.h minidlnatypes.h minissdp.h log.h
upnpevents.o: config.h upnpevents.h minidlnapath.h upnpglobalvars.h
upnpevents.o: minidlnatypes.h upnpdescgen.h log.h
upnpevents.o: minidlnatypes.h upnpdescgen.h log.h uuid.h
uuid.o: uuid.h
testupnpdescgen.o: config.h upnpdescgen.h
upnpdescgen.o: config.h upnpdescgen.h minidlnapath.h upnpglobalvars.h
upnpdescgen.o: minidlnatypes.h upnpdescstrings.h

View File

@ -1,35 +0,0 @@
/* MiniUPnP project
* (c) 2006-2007 Thomas Bernard
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef __COMMONRDR_H__
#define __COMMONRDR_H__
#include "config.h"
/* init and shutdown functions */
int
init_redirect(void);
void
shutdown_redirect(void);
/* get_redirect_rule() gets internal IP and port from
* interface, external port and protocl
*/
int
get_redirect_rule(const char * ifname, unsigned short eport, int proto,
char * iaddr, int iaddrlen, unsigned short * iport,
char * desc, int desclen,
u_int64_t * packets, u_int64_t * bytes);
int
get_redirect_rule_by_index(int index,
char * ifname, unsigned short * eport,
char * iaddr, int iaddrlen, unsigned short * iport,
int * proto, char * desc, int desclen,
u_int64_t * packets, u_int64_t * bytes);
#endif

View File

@ -1,8 +1,8 @@
#! /bin/sh
# $Id$
# miniupnp daemon
# http://miniupnp.free.fr or http://miniupnp.tuxfamily.org/
# (c) 2006-2007 Thomas Bernard
# MiniDLNA project
# http://sourceforge.net/projects/minidlna/
# (c) 2008-2009 Justin Maggard
# This software is subject to the conditions detailed in the
# LICENCE file provided within the distribution
@ -25,7 +25,6 @@ ${RM} ${CONFIGFILE}
# Detect if there are missing headers
# NOTE: This check only works with a normal distro
[ ! -e "/usr/include/sqlite3.h" ] && MISSING="libsqlite3 $MISSING"
[ ! -e "/usr/include/uuid/uuid.h" ] && MISSING="libuuid $MISSING"
[ ! -e "/usr/include/jpeglib.h" ] && MISSING="libjpeg $MISSING"
[ ! -e "/usr/include/libexif/exif-loader.h" ] && MISSING="libexif $MISSING"
[ ! -e "/usr/include/id3tag.h" ] && MISSING="libid3tag $MISSING"

View File

@ -45,7 +45,6 @@
#include "upnpevents.h"
#include "scanner.h"
#include "inotify.h"
#include "commonrdr.h"
#include "log.h"
#ifdef TIVO_SUPPORT
#include "tivo_beacon.h"

View File

@ -1,10 +1,15 @@
/* $Id$ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2008 Thomas Bernard
/* MiniDLNA project
* http://minidlna.sourceforge.net/
* (c) 2008-2009 Justin Maggard
*
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
* in the LICENCE file provided within the distribution
*
* Portions of the code from the MiniUPnP Project
* (c) Thomas Bernard licensed under BSD revised license
* detailed in the LICENSE.miniupnpd file provided within
* the distribution.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
@ -24,14 +29,9 @@
#include "minidlnapath.h"
#include "upnpglobalvars.h"
#include "upnpdescgen.h"
#include "uuid.h"
#include "log.h"
#define HAVE_UUID 1
#ifdef HAVE_UUID
#include <uuid/uuid.h>
#endif
/* stuctures definitions */
struct subscriber {
LIST_ENTRY(subscriber) entries;
@ -95,14 +95,12 @@ newSubscriber(const char * eventurl, const char * callback, int callbacklen)
tmp->callback[callbacklen] = '\0';
/* make a dummy uuid */
strncpy(tmp->uuid, uuidvalue, sizeof(tmp->uuid));
#ifdef HAVE_UUID
uuid_t uuid;
uuid_generate_time(uuid);
uuid_unparse_lower(uuid, tmp->uuid+5);
#else
tmp->uuid[sizeof(tmp->uuid)-1] = '\0';
snprintf(tmp->uuid+37, 5, "%04lx", random() & 0xffff);
#endif
if( get_uuid_string(tmp->uuid+5) != 0 )
{
tmp->uuid[sizeof(tmp->uuid)-1] = '\0';
snprintf(tmp->uuid+37, 5, "%04lx", random() & 0xffff);
}
return tmp;
}

View File

@ -1,9 +1,15 @@
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2008 Thomas Bernard
/* MiniDLNA project
* http://minidlna.sourceforge.net/
* (c) 2008-2009 Justin Maggard
*
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
* in the LICENCE file provided within the distribution
*
* Portions of the code from the MiniUPnP Project
* (c) Thomas Bernard licensed under BSD revised license
* detailed in the LICENSE.miniupnpd file provided within
* the distribution.
*/
#ifndef __UPNPEVENTS_H__
#define __UPNPEVENTS_H__
enum subscriber_service_enum {

View File

@ -1,10 +1,15 @@
/* $Id$ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006 Thomas Bernard
/* MiniDLNA project
* http://minidlna.sourceforge.net/
* (c) 2008-2009 Justin Maggard
*
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
* in the LICENCE file provided within the distribution
*
* Portions of the code from the MiniUPnP Project
* (c) Thomas Bernard licensed under BSD revised license
* detailed in the LICENSE.miniupnpd file provided within
* the distribution.
*/
#include <sys/types.h>
#include <netinet/in.h>

View File

@ -1,9 +1,15 @@
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006 Thomas Bernard
/* MiniDLNA project
* http://minidlna.sourceforge.net/
* (c) 2008-2009 Justin Maggard
*
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
* in the LICENCE file provided within the distribution
*
* Portions of the code from the MiniUPnP Project
* (c) Thomas Bernard licensed under BSD revised license
* detailed in the LICENSE.miniupnpd file provided within
* the distribution.
*/
#ifndef __UPNPGLOBALVARS_H__
#define __UPNPGLOBALVARS_H__

View File

@ -1,9 +1,10 @@
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006 Thomas Bernard
/* MiniDLNA project
* http://minidlna.sourceforge.net/
* (c) 2008-2009 Justin Maggard
*
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
* in the LICENCE file provided within the distribution
*/
#ifndef __UPNPSOAP_H__
#define __UPNPSOAP_H__

246
uuid.c Normal file
View File

@ -0,0 +1,246 @@
/* MiniDLNA project
*
* http://sourceforge.net/projects/minidlna/
* (c) 2009 Justin Maggard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution
*
* Much of this code and ideas for this code have been taken
* from Helge Deller's proposed Linux kernel patch (which
* apparently never made it upstream), and some from Busybox.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <errno.h>
#include "log.h"
#define ETH_ALEN 6
#define NSEC_PER_SEC 1000000000L
#define NSEC_PER_MSEC 1000000L
static u_int32_t clock_seq;
static const u_int32_t clock_seq_max = 0x3fff; /* 14 bits */
static int clock_seq_initialized;
unsigned long long
monotonic_us(void)
{
struct timespec ts;
syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;
}
int
read_bootid_node(u_int8_t *buf, size_t size)
{
FILE *boot_id;
if(size != 6)
return -1;
boot_id = fopen("/proc/sys/kernel/random/boot_id", "r");
if(!boot_id)
return -1;
if((fseek(boot_id, 24, SEEK_SET) < 0) ||
(fscanf(boot_id, "%02x%02x%02x%02x%02x%02x",
(unsigned *)&buf[0], (unsigned *)&buf[1], (unsigned *)&buf[2],
(unsigned *)&buf[3], (unsigned *)&buf[4], (unsigned *)&buf[5]) != 6))
{
fclose(boot_id);
return -1;
}
fclose(boot_id);
return 0;
}
static void
read_random_bytes(unsigned char *buf, size_t size)
{
int i;
pid_t pid;
i = open("/dev/urandom", O_RDONLY);
if(i >= 0)
{
read(i, buf, size);
close(i);
}
/* Paranoia. /dev/urandom may be missing.
* rand() is guaranteed to generate at least [0, 2^15) range,
* but lowest bits in some libc are not so "random". */
srand(monotonic_us());
pid = getpid();
while(1)
{
for(i = 0; i < size; i++)
buf[i] ^= rand() >> 5;
if(pid == 0)
break;
srand(pid);
pid = 0;
}
}
void
init_clockseq(void)
{
unsigned char buf[4];
read_random_bytes(buf, 4);
memcpy(&clock_seq, &buf, sizeof(clock_seq));
clock_seq &= clock_seq_max;
clock_seq_initialized = 1;
}
int
generate_uuid(unsigned char uuid_out[16])
{
static u_int64_t last_time_all;
static unsigned int clock_seq_started;
static char last_node[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
struct timespec ts;
u_int64_t time_all;
int inc_clock_seq = 0;
struct ifaddrs *ifaddr, *ifa;
unsigned char mac[6];
struct ifreq ifr;
int fd;
int found_mac = 0;
memset(&mac, '\0', sizeof(mac));
/* Get the spatially unique node identifier */
fd = socket(AF_INET, SOCK_DGRAM, 0);
if( fd < 0 )
return -1;
if(getifaddrs(&ifaddr) == -1)
{
DPRINTF(E_ERROR, L_HTTP, "getifaddrs(): %s\n", strerror(errno));
return -1;
}
for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if(ifa->ifa_addr->sa_family != AF_PACKET)
continue;
if(ifa->ifa_flags & IFF_LOOPBACK)
continue;
strcpy(ifr.ifr_name, ifa->ifa_name);
if(strncmp(last_node, ifa->ifa_name, sizeof(last_node)) != 0)
{
inc_clock_seq = 1;
strncpy(last_node, ifa->ifa_name, sizeof(last_node));
}
if(ioctl(fd, SIOCGIFHWADDR, &ifr) == 0)
memmove(mac, ifr.ifr_hwaddr.sa_data, 6);
found_mac = 1;
break;
}
close(fd);
freeifaddrs(ifaddr);
if(found_mac)
{
memcpy(&uuid_out[10], mac, ETH_ALEN);
}
else
{
/* use bootid's nodeID if no network interface found */
DPRINTF(E_INFO, L_HTTP, "Could not find MAC. Use bootid's nodeID.\n");
if( read_bootid_node(&uuid_out[10], 6) != 0)
{
DPRINTF(E_INFO, L_HTTP, "bootid node not successfully read.\n");
read_random_bytes(&uuid_out[10], 6);
}
}
/* Determine 60-bit timestamp value. For UUID version 1, this is
* represented by Coordinated Universal Time (UTC) as a count of 100-
* nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
* Gregorian reform to the Christian calendar).
*/
syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts);
time_all = ((u_int64_t)ts.tv_sec) * (NSEC_PER_SEC / 100);
time_all += ts.tv_nsec / 100;
/* add offset from Gregorian Calendar to Jan 1 1970 */
time_all += 12219292800000ULL * (NSEC_PER_MSEC / 100);
time_all &= 0x0fffffffffffffffULL; /* limit to 60 bits */
/* Determine clock sequence (max. 14 bit) */
if(!clock_seq_initialized)
{
init_clockseq();
clock_seq_started = clock_seq;
}
else
{
if(inc_clock_seq || time_all <= last_time_all)
{
clock_seq = (clock_seq + 1) & clock_seq_max;
if(clock_seq == clock_seq_started)
{
clock_seq = (clock_seq - 1) & clock_seq_max;
}
}
else
clock_seq_started = clock_seq;
}
last_time_all = time_all;
/* Fill in timestamp and clock_seq values */
uuid_out[3] = (u_int8_t)time_all;
uuid_out[2] = (u_int8_t)(time_all >> 8);
uuid_out[1] = (u_int8_t)(time_all >> 16);
uuid_out[0] = (u_int8_t)(time_all >> 24);
uuid_out[5] = (u_int8_t)(time_all >> 32);
uuid_out[4] = (u_int8_t)(time_all >> 40);
uuid_out[7] = (u_int8_t)(time_all >> 48);
uuid_out[6] = (u_int8_t)(time_all >> 56);
uuid_out[8] = clock_seq >> 8;
uuid_out[9] = clock_seq & 0xff;
/* Set UUID version to 1 --- time-based generation */
uuid_out[6] = (uuid_out[6] & 0x0F) | 0x10;
/* Set the UUID variant to DCE */
uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;
return 0;
}
/* Places a null-terminated 37-byte time-based UUID string in the buffer pointer to by buf.
* A large enough buffer must already be allocated. */
int
get_uuid_string(char *buf)
{
unsigned char uuid[16];
if( generate_uuid(uuid) != 0 )
return -1;
sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8],
uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
buf[36] = '\0';
return 0;
}

16
uuid.h Normal file
View File

@ -0,0 +1,16 @@
/* UUID generation functions
*
* Project : minidlna
* Website : http://sourceforge.net/projects/minidlna/
* Author : Justin Maggard
* Copyright (c) 2009 Justin Maggard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef __UUID_H__
#define __UUID_H__
int
get_uuid_string(char *buf);
#endif