Description: Add upnp_log_filename option for libupnp debug,
 and use that file for our own debug log.
Author: Nick Leverton <nick@leverton.org>

Index: linux-igd-1.0+cvs20070630-libupnp6/config.c
===================================================================
--- linux-igd-1.0+cvs20070630-libupnp6.orig/config.c	2014-10-07 23:35:48.000000000 +0100
+++ linux-igd-1.0+cvs20070630-libupnp6/config.c	2014-10-07 23:35:53.000000000 +0100
@@ -63,6 +63,8 @@
     regex_t re_xml_path;
     regex_t re_listenport;
     regex_t re_paranoid;
+    regex_t re_upnp_log_filename;
+    regex_t re_upnp_log_level;
 
     // Make sure all vars are 0 or \0 terminated
     vars->debug = 0;
@@ -78,6 +80,8 @@
     strcpy(vars->xmlPath,"");
     vars->listenport = 0;
     vars->paranoid = 0;
+    strcpy(vars->upnp_log_filename,"");
+    vars->upnp_log_level = UPNP_INFO;
 
     // Regexp to match a comment line
     regcomp(&re_comment,"^[[:blank:]]*#",0);
@@ -97,6 +101,8 @@
     regcomp(&re_xml_path,"xml_document_path[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
     regcomp(&re_listenport,"listenport[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
     regcomp(&re_paranoid,"paranoid[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
+    regcomp(&re_upnp_log_filename,"upnp_log_filename[[:blank:]]*=[[:blank:]]*\"([^\"]+)\"",REG_EXTENDED);
+    regcomp(&re_upnp_log_level,"upnp_log_level[[:blank:]]*=[[:blank:]]*(UPNP_CRITICAL|UPNP_PACKET|UPNP_INFO|UPNP_ALL)",REG_EXTENDED);
 
     if ((conf_file=fopen(CONF_FILE,"r")) != NULL)
     {
@@ -174,6 +180,23 @@
 		  getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
 		  vars->paranoid = atoi(tmp);
 		}
+		else if (regexec(&re_upnp_log_filename,line,NMATCH,submatch,0) == 0)
+		{
+		  getConfigOptionArgument(vars->upnp_log_filename, PATH_LEN, line, submatch);
+		}
+		else if (regexec(&re_upnp_log_level,line,NMATCH,submatch,0) == 0)
+		{
+		  char tmp[15];
+		  getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
+		  if( 0 == strcmp(tmp, "UPNP_ALL") )
+		    vars->upnp_log_level = UPNP_ALL;
+		  else if( 0 == strcmp(tmp, "UPNP_INFO") )
+		    vars->upnp_log_level = UPNP_INFO;
+		  else if( 0 == strcmp(tmp, "UPNP_PACKET") )
+		    vars->upnp_log_level = UPNP_PACKET;
+		  else if( 0 == strcmp(tmp, "UPNP_CRITICAL") )
+		    vars->upnp_log_level = UPNP_CRITICAL;
+		}
 		else
 		{
 		    // We end up here if ther is an unknown config directive
@@ -198,6 +221,8 @@
     regfree(&re_xml_path);
     regfree(&re_listenport);
     regfree(&re_paranoid);
+    regfree(&re_upnp_log_filename);
+    regfree(&re_upnp_log_level);
     // Set default values for options not found in config file
     if (strnlen(vars->forwardChainName, CHAIN_NAME_LEN) == 0)
     {
Index: linux-igd-1.0+cvs20070630-libupnp6/etc/upnpd.conf
===================================================================
--- linux-igd-1.0+cvs20070630-libupnp6.orig/etc/upnpd.conf	2014-10-07 23:35:48.000000000 +0100
+++ linux-igd-1.0+cvs20070630-libupnp6/etc/upnpd.conf	2014-10-07 23:35:53.000000000 +0100
@@ -101,3 +101,20 @@
 # 1, only allow internal hosts to forward to themselves.
 # default = 0
 paranoid = 0
+
+# libupnp debug log file name
+#  If this setting is enabled then linux-igd debug entries will also be written
+#  to this file as well as to syslog (see debug_mode, above).  This makes it
+#  easier to debug linux-igd without having to enable all debug-level messages
+#  in syslog.  You are responsible for clearing or rotating this file yourself.
+# allowed values: any valid filename, relative or absolute.  Must not be blank
+# default = none
+#upnp_log_filename = "/var/log/linux-igd.log"
+
+# libupnp debug logging level
+#  UPNP_CRITICAL
+#  UPNP_PACKET
+#  UPNP_INFO
+#  UPNP_ALL
+# default = UPNP_INFO
+upnp_log_level = UPNP_CRITICAL
Index: linux-igd-1.0+cvs20070630-libupnp6/globals.h
===================================================================
--- linux-igd-1.0+cvs20070630-libupnp6.orig/globals.h	2014-10-07 23:35:48.000000000 +0100
+++ linux-igd-1.0+cvs20070630-libupnp6/globals.h	2014-10-07 23:35:53.000000000 +0100
@@ -3,6 +3,9 @@
 
 #include <net/if.h>
 
+#include <upnp.h>
+#include <upnpdebug.h>
+
 #define CHAIN_NAME_LEN 32
 #define BITRATE_LEN 32
 #define PATH_LEN 64
@@ -37,6 +40,8 @@
   char descDocName[PATH_LEN];
   char xmlPath[PATH_LEN];
   int listenport;	//The port to listen on
+  char upnp_log_filename[PATH_LEN];	// The file for libupnp debug logging
+  Upnp_LogLevel upnp_log_level;
 };
 
 typedef struct GLOBALS* globals_p;
Index: linux-igd-1.0+cvs20070630-libupnp6/main.c
===================================================================
--- linux-igd-1.0+cvs20070630-libupnp6.orig/main.c	2014-10-07 23:35:49.000000000 +0100
+++ linux-igd-1.0+cvs20070630-libupnp6/main.c	2014-10-07 23:35:53.000000000 +0100
@@ -16,6 +16,8 @@
 #include "util.h"
 #include "pmlist.h"
 
+#include <upnpdebug.h>
+
 // Global variables
 globals g_vars;
 
@@ -112,6 +114,10 @@
 
 	openlog("upnpd", LOG_CONS | LOG_NDELAY | LOG_PID | (foreground ? LOG_PERROR : 0), LOG_LOCAL6);
 
+	// Set up libupnp debug logging
+	UpnpSetLogFileNames(NULL, g_vars.upnp_log_filename);
+	UpnpSetLogLevel(g_vars.upnp_log_level);
+
 	// Initialize UPnP SDK on the internal Interface
 	trace(3, "Initializing UPnP SDK ... ");
 	if ( (ret = UpnpInit(intIpAddress,g_vars.listenport) ) != UPNP_E_SUCCESS)
@@ -132,7 +138,7 @@
 		UpnpFinish();
 		exit(1);
 	}
-	trace(2, "Succesfully set the Web Server Root Directory.");
+	trace(2, "Successfully set the Web Server Root Directory.");
 
 	//initialize the timer thread for expiration of mappings
 	if (ExpirationTimerThreadInit()!=0) {
Index: linux-igd-1.0+cvs20070630-libupnp6/util.c
===================================================================
--- linux-igd-1.0+cvs20070630-libupnp6.orig/util.c	2014-10-07 23:35:52.000000000 +0100
+++ linux-igd-1.0+cvs20070630-libupnp6/util.c	2014-10-07 23:35:53.000000000 +0100
@@ -12,6 +12,7 @@
 #include "globals.h"
 
 #include <ithread.h>
+#include <upnpdebug.h>
 
 static int get_sockfd(void)
 {
@@ -63,13 +64,21 @@
   va_start(ap, format);
 
   if( -1 == asprintf(&thr_format, "0x%lx %s", (unsigned long int)ithread_self(), format) )
-    thr_format = format;
+    thr_format = (char *)format;
 
   if (g_vars.debug >= debuglevel) {
+    FILE * upnp_fd = UpnpGetDebugFile(UPNP_ALL, 0);
     vsyslog(LOG_DEBUG, thr_format,  ap);
+    va_end(ap);
+    va_start(ap, format);
+    if( NULL != upnp_fd )
+    {
+      vfprintf(upnp_fd, thr_format, ap);
+      fprintf(upnp_fd, "\n");
+    }
   }
 
-  if( thr_format != format )
+  if( thr_format != (char *)format )
     free(thr_format);
 
   va_end(ap);
