diff --git a/Makefile b/Makefile index f725c1f..d2875c8 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/commonrdr.h b/commonrdr.h deleted file mode 100644 index 7efc3de..0000000 --- a/commonrdr.h +++ /dev/null @@ -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 - diff --git a/genconfig.sh b/genconfig.sh index dc3c591..9be8cf0 100755 --- a/genconfig.sh +++ b/genconfig.sh @@ -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" diff --git a/minidlna.c b/minidlna.c index 00286aa..d903ca5 100644 --- a/minidlna.c +++ b/minidlna.c @@ -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" diff --git a/upnpevents.c b/upnpevents.c index 3ec8a4d..f07055d 100644 --- a/upnpevents.c +++ b/upnpevents.c @@ -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 #include #include @@ -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 -#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; } diff --git a/upnpevents.h b/upnpevents.h index 253e0c6..fe1a273 100644 --- a/upnpevents.h +++ b/upnpevents.h @@ -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 { diff --git a/upnpglobalvars.c b/upnpglobalvars.c index c13f2c6..f4150f5 100644 --- a/upnpglobalvars.c +++ b/upnpglobalvars.c @@ -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 #include diff --git a/upnpglobalvars.h b/upnpglobalvars.h index f71ac97..c626e31 100644 --- a/upnpglobalvars.h +++ b/upnpglobalvars.h @@ -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__ diff --git a/upnpsoap.h b/upnpsoap.h index 6abe140..ca15ad1 100644 --- a/upnpsoap.h +++ b/upnpsoap.h @@ -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__ diff --git a/uuid.c b/uuid.c new file mode 100644 index 0000000..56dd49f --- /dev/null +++ b/uuid.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/uuid.h b/uuid.h new file mode 100644 index 0000000..00c0612 --- /dev/null +++ b/uuid.h @@ -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