]> git.ipfire.org Git - thirdparty/sarg.git/commitdiff
IP address resolution using one external program
authorFrédéric Marchal <fmarchal@users.sourceforge.net>
Mon, 21 May 2012 19:55:47 +0000 (21:55 +0200)
committerFrédéric Marchal <fmarchal@users.sourceforge.net>
Mon, 21 May 2012 19:55:47 +0000 (21:55 +0200)
It is now possible to resolve an IP address using an external program.
Only one external program can be configured but it may do anything
including attempting several strategies to resolve the IP address.

The module may be chained after the standard dns module to get the name of
a computer not registered with the DNS.

Executing an external program is exceedingly slow so it is best to try
the DNS first!

CMakeLists.txt
Makefile.in
include/ip2name.h
ip2name.c
ip2name_exec.c [new file with mode: 0644]
sarg.conf

index 0000eb98be5c27cf153e3d134f1d7f0eeb3d1fd1..2736fe729cb239b6707646e9100482b117112494 100755 (executable)
@@ -52,7 +52,7 @@ SET(SRC util.c log.c report.c topuser.c email.c sort.c html.c
        useragent.c exclude.c convlog.c totday.c repday.c datafile.c
        indexonly.c splitlog.c lastlog.c topsites.c siteuser.c css.c
        smartfilter.c denied.c authfail.c charset.c dichotomic.c
-       redirector.c auth.c download.c grepday.c
+       redirector.c auth.c download.c grepday.c ip2name_exec.c
        dansguardian_log.c dansguardian_report.c realtime.c btree_cache.c
        usertab.c userinfo.c longline.c url.c)
 
index 4595f81b12cd31d6d32c5714d76a5029f209e120..42e7c58b06b7ac05fd8ac420a002dcbedec0baa0 100644 (file)
@@ -36,7 +36,7 @@ SRCS = util.c log.c report.c topuser.c email.c sort.c html.c \
        useragent.c exclude.c convlog.c totday.c repday.c datafile.c\
        indexonly.c splitlog.c lastlog.c topsites.c siteuser.c css.c \
        smartfilter.c denied.c authfail.c charset.c dichotomic.c \
-       redirector.c auth.c download.c grepday.c \
+       redirector.c auth.c download.c grepday.c ip2name_exec.c \
        dansguardian_log.c dansguardian_report.c realtime.c btree_cache.c \
        usertab.c userinfo.c longline.c url.c
 
index 42d62fed86a831fac090c6ed4bd5eabae261e4ff..3a894f7a4c2c77189296ecc162507b60e7b5218b 100644 (file)
@@ -4,7 +4,7 @@
 //! The possible return code of ip2name subfunctions.
 enum ip2name_retcode
 {
-       //! Error encountered during the 
+       //! Error encountered during the processing.
        INRC_Error=-1,
        //! No match found.
        INRC_NotFound,
@@ -21,9 +21,9 @@ struct Ip2NameProcess
        //! The link to the next module to try if this one fails.
        struct Ip2NameProcess *Next;
        //! The function to configure the module.
-       int (*Configure)(const char *param);
+       void (*Configure)(const char *name,const char *param);
        //! Function to resolve an IP address into a name.
        enum ip2name_retcode (*Resolve)(char *ip,int ip_len);
 };
 
-#endif //IP2NAME_HEADER
\ No newline at end of file
+#endif //IP2NAME_HEADER
index 5e7825e4d1346373f43b5589afd3b0d11b32b06e..3f6b3e5175ec88f1a009b4d2f845cb295d1ae6b3 100644 (file)
--- a/ip2name.c
+++ b/ip2name.c
@@ -39,11 +39,13 @@ struct Ip2NameModules
 };
 
 extern struct Ip2NameProcess Ip2NameDns;
+extern struct Ip2NameProcess Ip2NameExec;
 
 //! The list of the modules available to resolve an IP address into a name.
 static const struct Ip2NameModules ModulesList[]=
 {
        {"dns",&Ip2NameDns},
+       {"exec",&Ip2NameExec},
        {"yes",&Ip2NameDns},//for historical compatibility
        {"no",NULL},//does nothing for compatibility with previous versions
 };
@@ -111,6 +113,34 @@ static void ip2name_buildmoduleslist(const char *list)
        }
 }
 
+/*!
+Configure a module whose name is given as an argument. The parameters to configure
+follow the module name after one or more space or tabs.
+
+\param module The name of the module, a space and the configuration options.
+*/
+static void ip2name_configmodule(const char *module)
+{
+       int length;
+       unsigned int ModuleIdx;
+       
+       for (length=0 ; module[length] && (unsigned char)module[length]>' ' ; length++);
+       for (ModuleIdx=0 ; ModuleIdx<sizeof(ModulesList)/sizeof(*ModulesList) ; ModuleIdx++) {
+               if (strncasecmp(module,ModulesList[ModuleIdx].Name,length)==0 && ModulesList[ModuleIdx].Name[length]=='\0') {
+                       // module found
+                       if (ModulesList[ModuleIdx].Process) {
+                               if (!ModulesList[ModuleIdx].Process->Configure) {
+                                       debuga(_("No option to configure for module %s\n"),ModulesList[ModuleIdx].Name);
+                                       exit(EXIT_FAILURE);
+                               }
+                               while (module[length] && (unsigned char)module[length]<=' ') length++;
+                               ModulesList[ModuleIdx].Process->Configure(ModulesList[ModuleIdx].Name,module+length);
+                       }
+                       break;
+               }
+       }
+}
+
 /*!
 Configure a module to resolve an IP address into a name.
 
@@ -130,6 +160,8 @@ int ip2name_config(const char *param)
        
        // parameter for a module?
        if (*param=='_') {
+               ip2name_configmodule(param+1);
+               return(1);
        }
        
        return(0);
diff --git a/ip2name_exec.c b/ip2name_exec.c
new file mode 100644 (file)
index 0000000..306d7d9
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
+ *                                                            1998, 2012
+ *
+ * SARG donations:
+ *      please look at http://sarg.sourceforge.net/donations.php
+ * Support:
+ *     http://sourceforge.net/projects/sarg/forums/forum/363374
+ * ---------------------------------------------------------------------
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "include/conf.h"
+#include "include/defs.h"
+#include "include/ip2name.h"
+
+//! The buffer size to store the command.
+#define CMD_BUFFER_SIZE 2048
+
+static void ip2name_execconfig(const char *name,const char *param);
+static enum ip2name_retcode ip2name_exec(char *ip,int ip_len);
+
+//! The functions to resolve an IP address using an external executable.
+struct Ip2NameProcess Ip2NameExec=
+{
+       "dns",
+       NULL,//no next item yet
+       ip2name_execconfig,
+       ip2name_exec
+};
+
+static char ExecCmd[CMD_BUFFER_SIZE]="";
+
+/*!
+Configure the module to resolve an IP address using an external program.
+
+\param name The name of the module as invoked by the user in the configuration
+file.
+\param param The parameters passed to the module.
+*/
+static void ip2name_execconfig(const char *name,const char *param)
+{
+       int len;
+       
+       len=strlen(param);
+       if (len>=sizeof(ExecCmd)) {
+               debuga(_("Command to execute to resolve the IP addresses is too long (maximum is %lu bytes)\n"),sizeof(ExecCmd));
+               exit(EXIT_FAILURE);
+       }
+       strcpy(ExecCmd,param);
+}
+
+/*!
+Run an external process to get the name of a computer.
+
+\param ip The ip address.
+\param ip_len The number of bytes in the IP address.
+
+\return One of the ::ip2name_retcode value.
+*/
+static enum ip2name_retcode ip2name_exec(char *ip,int ip_len)
+{
+       char cmd[CMD_BUFFER_SIZE];
+       int i;
+       int j;
+       int len;
+       FILE *cmd_in;
+       char buffer[512];
+       size_t nread;
+       
+       if (ExecCmd[0]=='\0') {
+               debuga(_("No command to run to resolve an IP address. Please configure it in sarg.conf\n"));
+               exit(EXIT_FAILURE);
+       }
+       
+       j=0;
+       len=strlen(ip);
+       for (i=0 ; i<sizeof(ExecCmd) && ExecCmd[i] ; i++) {
+               if (ExecCmd[i]=='%' && strncmp(ExecCmd+i+1,"IP",2)==0) {
+                       if (j+len>=sizeof(cmd)) {
+                               debuga(_("IP address %s too long for the command to run\n"),ip);
+                               return(INRC_Error);
+                       }
+                       strcpy(cmd+j,ip);
+                       j+=len;
+                       i+=2;
+               } else {
+                       if (j>=sizeof(cmd)) {
+                               debuga(_("IP address %.*s too long for the command to run\n"),ip_len,ip);
+                               return(INRC_Error);
+                       }
+                       cmd[j++]=ExecCmd[i];
+               }
+       }
+       cmd[j]='\0';
+       
+       cmd_in=popen(cmd,"r");
+       if (!cmd_in) {
+               debuga(_("Cannot run command %s\n"),cmd);
+               exit(EXIT_FAILURE);
+       }
+       
+       nread=fread(buffer,1,sizeof(buffer),cmd_in);
+       
+       if (pclose(cmd_in)==-1) {
+               debuga(_("Command failed: %s\n"),cmd);
+               exit(EXIT_FAILURE);
+       }
+
+       if (nread==0) return(INRC_NotFound);
+       
+       safe_strcpy(ip,buffer,ip_len);
+       return(INRC_Found);
+}
index a405476bbdcf896a5bc2613c3641efefda162d4a..f474428b09a2d93849c445a8cd06257da6d4a61a 100644 (file)
--- a/sarg.conf
+++ b/sarg.conf
 #
 #       The possible modules are
 #         dns Use the DNS.
+#         exec Call an external program with the IP address as argument.
 #
 #       For compatibility with previous versions, yes is a synonymous for dns and
 #       no does nothing.
 #       sarg -n forces the use of the dns module.
 #resolve_ip no
 
+# TAG:  resolve_ip_exec command
+#       If resolve_ip selects the exec module, this is the command to run to
+#       resolve an IP address. The command must contain a placeholder where the
+#       IP address is inserted. The placeholder must be %IP in uppercases. The
+#       placeholder may be repeated multiple times if necessary.
+#
+#       The command is expected to return the host name without frills on its
+#       standard output. If the command returns nothing, it is assumed that the
+#       command could not resolve the IP address and the next module in the
+#       chain is given a try with the same address.
+#
+#       This option can only be used once. Therefore there is only one command
+#       available to resolve an IP address but the program can do anything it
+#       deems fit including attempting several strategies.
+#
+#       Beware that running an external program is exceedingly slow. So you
+#       should try the DNS first and only call an external program if the DNS
+#       fails.
+#resolve_ip_exec nmblookup -A %IP | sed -n -e 's/^ *\(.*\) *<00> - *B.*/\1/p'
+
 # TAG:  user_ip yes/no
 #       Use Ip Address instead userid in reports.
 #       sarg -p