added capability to use a local interface IP address as fromhost-ip for imuxsock
authorRainer Gerhards <rgerhards@adiscon.com>
Tue, 6 Mar 2012 16:26:04 +0000 (17:26 +0100)
committerRainer Gerhards <rgerhards@adiscon.com>
Tue, 6 Mar 2012 16:26:04 +0000 (17:26 +0100)
new config directives: $IMUXSockLocalIPIF

ChangeLog
doc/imuxsock.html
plugins/imuxsock/imuxsock.c
runtime/net.c
runtime/net.h
tools/syslogd.c

index 99e324a..78f7469 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+- added capability to use a local interface IP address as fromhost-ip for
+  imuxsock
+  new config directives: $IMUXSockLocalIPIF
 - added configuration directives to customize queue light delay marks
   $MainMsgQueueLightDelayMark, $ActionQueueLightDelayMark; both
   specify number of messages starting at which a delay happens.
index ee5db22..1b79dd0 100644 (file)
@@ -64,6 +64,11 @@ burst in number of messages. Default is 200.
 <li><b>$IMUXSockRateLimitSeverity</b> [numerical severity] - specifies the severity of
 messages that shall be rate-limited.
 </li>
+<li><b>$IMUXSockLocalIPIF</b> [interface name] - if provided, the IP of the specified
+interface (e.g. "eth0") shall be used as fromhost-ip for imuxsock-originating messages.
+If this directive is not given OR the interface cannot be found (or has no IP address),
+the default of "127.0.0.1" is used.
+</li>
 <li><b>$InputUnixListenSocketUsePIDFromSystem</b> [on/<b>off</b>] - specifies if the pid being logged shall
 be obtained from the log socket itself. If so, the TAG part of the message is rewritten.
 It is recommended to turn this option on, but the default is "off" to keep compatible
@@ -150,7 +155,7 @@ $SystemLogRateLimitInterval 0 # turn off rate limiting
 <p><font size="2">This documentation is part of the
 <a href="http://www.rsyslog.com/">rsyslog</a>
 project.<br>
-Copyright &copy; 2008-2010 by <a href="http://www.gerhards.net/rainer">Rainer
+Copyright &copy; 2008-2012 by <a href="http://www.gerhards.net/rainer">Rainer
 Gerhards</a> and
 <a href="http://www.adiscon.com/">Adiscon</a>.
 Released under the GNU GPL version 3 or higher.</font></p>
index 4523798..ad8c81e 100644 (file)
@@ -89,6 +89,7 @@ DEF_IMOD_STATIC_DATA
 DEFobjCurrIf(errmsg)
 DEFobjCurrIf(glbl)
 DEFobjCurrIf(prop)
+DEFobjCurrIf(net)
 DEFobjCurrIf(parser)
 DEFobjCurrIf(datetime)
 DEFobjCurrIf(statsobj)
@@ -157,6 +158,7 @@ static int sd_fds = 0;                      /* number of systemd activated sockets */
 /* config settings */
 static int bOmitLocalLogging = 0;
 static uchar *pLogSockName = NULL;
+static uchar *pLocalIPIF = NULL;
 static uchar *pLogHostName = NULL;     /* host name to use with this socket */
 static int bUseFlowCtl = 0;            /* use flow control or not (if yes, only LIGHT is used! */
 static int bIgnoreTimestamp = 1;       /* ignore timestamps present in the incoming message? */
@@ -764,6 +766,8 @@ ENDrunInput
 
 
 BEGINwillRun
+       uchar myIP[128];
+       rsRetVal localRet;
 CODESTARTwillRun
        register int i;
        int actSocks;
@@ -784,7 +788,7 @@ CODESTARTwillRun
        else if(sd_booted()) {
                struct stat st;
                if(stat(SYSTEMD_JOURNAL, &st) != -1 && S_ISDIR(st.st_mode)) {
-                       listeners[0].sockName = SYSTEMD_PATH_LOG;
+                       listeners[0].sockName = (uchar*)SYSTEMD_PATH_LOG;
                }
        }
        if(ratelimitIntervalSysSock > 0) {
@@ -826,6 +830,23 @@ CODESTARTwillRun
        CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imuxsock"), sizeof("imuxsock") - 1));
        CHKiRet(prop.ConstructFinalize(pInputName));
 
+       if(pLocalIPIF == NULL) {
+               strcpy((char*)myIP, "127.0.0.1");
+       } else {
+               localRet = net.GetIFIPAddr((uchar*)"eth0", AF_UNSPEC, myIP, (int) sizeof(myIP));
+               if(localRet != RS_RET_OK) {
+                       DBGPRINTF("imuxsock: could not obtain my IP, using 127.0.0.1 instead\n");
+                       strcpy((char*)myIP, "127.0.0.1");
+               }
+       }
+
+       DBGPRINTF("imuxsock: using '%s' as localhost IP\n", myIP);
+
+       CHKiRet(prop.Construct(&pLocalHostIP));
+       CHKiRet(prop.SetString(pLocalHostIP, myIP, ustrlen(myIP)));
+       CHKiRet(prop.ConstructFinalize(pLocalHostIP));
+
+
 finalize_it:
 ENDwillRun
 
@@ -857,6 +878,7 @@ CODESTARTafterRun
                }
        /* free no longer needed string */
        free(pLogSockName);
+       free(pLocalIPIF);
        free(pLogHostName);
 
        discardLogSockets();
@@ -901,6 +923,10 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
                free(pLogSockName);
                pLogSockName = NULL;
        }
+       if(pLocalIPIF != NULL) {
+               free(pLocalIPIF);
+               pLocalIPIF = NULL;
+       }
        if(pLogHostName != NULL) {
                free(pLogHostName);
                pLogHostName = NULL;
@@ -931,6 +957,7 @@ CODESTARTmodInit
 CODEmodInit_QueryRegCFSLineHdlr
        CHKiRet(objUse(errmsg, CORE_COMPONENT));
        CHKiRet(objUse(glbl, CORE_COMPONENT));
+       CHKiRet(objUse(net, CORE_COMPONENT));
        CHKiRet(objUse(prop, CORE_COMPONENT));
        CHKiRet(objUse(statsobj, CORE_COMPONENT));
        CHKiRet(objUse(datetime, CORE_COMPONENT));
@@ -954,10 +981,6 @@ CODEmodInit_QueryRegCFSLineHdlr
                listeners[i].fd  = -1;
        }
 
-       CHKiRet(prop.Construct(&pLocalHostIP));
-       CHKiRet(prop.SetString(pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
-       CHKiRet(prop.ConstructFinalize(pLocalHostIP));
-
        /* now init listen socket zero, the local log socket */
        CHKiRet(prop.Construct(&(listeners[0].hostName)));
        CHKiRet(prop.SetString(listeners[0].hostName, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())));
@@ -988,6 +1011,8 @@ CODEmodInit_QueryRegCFSLineHdlr
                NULL, &ratelimitSeverity, STD_LOADABLE_MODULE_ID));
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
                resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+       CHKiRet(omsdRegCFSLineHdlr((uchar *)"imuxsocklocalipif", 0, eCmdHdlrGetWord,
+               NULL, &pLocalIPIF, STD_LOADABLE_MODULE_ID));
        /* the following one is a (dirty) trick: the system log socket is not added via
         * an "addUnixListenSocket" config format. As such, it's properties can not be modified
         * via $InputUnixListenSocket*". So we need to add a special directive
index 4781739..1264b2c 100644 (file)
@@ -12,7 +12,7 @@
  * long term, but it is good to have it out of syslogd.c. Maybe this here is
  * an interim location ;)
  *
- * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
  *
  * rgerhards, 2008-04-16: I changed this code to LGPL today. I carefully analyzed
  * that it does not borrow code from the original sysklogd and that I have 
@@ -54,6 +54,9 @@
 #include <fnmatch.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <ifaddrs.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
 
 #include "syslogd-types.h"
 #include "module-template.h"
@@ -1581,6 +1584,54 @@ finalize_it:
 }
 
 
+/* return the IP address (IPv4/6) for the provided interface. Returns
+ * RS_RET_NOT_FOUND if interface can not be found in interface list.
+ * The family must be correct (AF_INET vs. AF_INET6, AF_UNSPEC means
+ * either of *these two*).
+ * The function re-queries the interface list (at least in theory).
+ * However, it caches entries in order to avoid too-frequent requery.
+ * rgerhards, 2012-03-06
+ */
+static rsRetVal
+getIFIPAddr(uchar *szif, int family, uchar *pszbuf, int lenBuf)
+{
+       struct ifaddrs * ifaddrs = NULL;
+       struct ifaddrs * ifa;
+       void * pAddr;
+       DEFiRet;
+
+       if(getifaddrs(&ifaddrs) != 0) {
+               ABORT_FINALIZE(RS_RET_ERR);
+       }
+
+       for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+               if(strcmp(ifa->ifa_name, (char*)szif))
+                       continue;
+               if(   (family == AF_INET6 || family == AF_UNSPEC)
+                  && ifa->ifa_addr->sa_family == AF_INET6) {
+                       pAddr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+                       inet_ntop(AF_INET6, pAddr, (char*)pszbuf, lenBuf);
+                       break;
+               } else if(/*   (family == AF_INET || family == AF_UNSPEC)
+                        &&*/ ifa->ifa_addr->sa_family == AF_INET) {
+                       pAddr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
+                       inet_ntop(AF_INET, pAddr, (char*)pszbuf, lenBuf);
+                       break;
+               } 
+       }
+
+       if(ifaddrs != NULL)
+               freeifaddrs(ifaddrs);
+
+       if(ifa == NULL)
+               iRet = RS_RET_NOT_FOUND;
+
+finalize_it:
+       RETiRet;
+
+}
+
+
 /* queryInterface function
  * rgerhards, 2008-03-05
  */
@@ -1612,6 +1663,7 @@ CODESTARTobjQueryInterface(net)
        pIf->PermittedPeerWildcardMatch = PermittedPeerWildcardMatch;
        pIf->CmpHost = CmpHost;
        pIf->HasRestrictions = HasRestrictions;
+       pIf->GetIFIPAddr = getIFIPAddr;
        /* data members */
        pIf->pACLAddHostnameOnFail = &ACLAddHostnameOnFail;
        pIf->pACLDontResolve = &ACLDontResolve;
index 101ce79..1b41c81 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions for network-related stuff.
  *
- * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
  *
  * This file is part of the rsyslog runtime library.
  *
@@ -151,11 +151,13 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */
        /* v6 interface additions - 2009-11-16 */
        rsRetVal (*HasRestrictions)(uchar *, int *bHasRestrictions);
        int (*isAllowedSender2)(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS);
+       /* v7 interface additions - 2012-03-06 */
+       rsRetVal (*GetIFIPAddr)(uchar *szif, int family, uchar *pszbuf, int lenBuf);
        /* data members - these should go away over time... TODO */
        int    *pACLAddHostnameOnFail; /* add hostname to acl when DNS resolving has failed */
        int    *pACLDontResolve;       /* add hostname to acl instead of resolving it to IP(s) */
 ENDinterface(net)
-#define netCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */
+#define netCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */
 
 /* prototypes */
 PROTOTYPEObj(net);
index c0e663d..02a0dad 100644 (file)
@@ -2712,6 +2712,7 @@ int realMain(int argc, char **argv)
                                CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_aliases[i]));
                        } else {
                                CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_name));
+                               int i;
                        }
 
                        if((p = (uchar*)strchr((char*)LocalHostName, '.')))