milestone: added capability to use a local interface IP address as fromhost-ip
authorRainer Gerhards <rgerhards@adiscon.com>
Wed, 21 Mar 2012 10:43:45 +0000 (11:43 +0100)
committerRainer Gerhards <rgerhards@adiscon.com>
Wed, 21 Mar 2012 10:43:45 +0000 (11:43 +0100)
... for locally originating messages. New directive $LocalHostIPIF.
Note that not all modules yet support this new directive - next step...

ChangeLog
doc/rsyslog_conf_global.html
plugins/impstats/impstats.c
runtime/glbl.c
runtime/glbl.h
tools/syslogd.c

index f2a4e86..b9e56ec 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,8 +2,7 @@
   for imtcp, directive is $InputTCPServerSupportOctetCountedFraming 
   for imptcp, directive is $InputPTCPServerSupportOctetCountedFraming 
 - added capability to use a local interface IP address as fromhost-ip for
-  imuxsock imklog
-  new config directives: $IMUXSockLocalIPIF, $klogLocalIPIF
+  locally originating messages. New directive $LocalHostIPIF
 - added configuration directives to customize queue light delay marks
   $MainMsgQueueLightDelayMark, $ActionQueueLightDelayMark; both
   specify number of messages starting at which a delay happens.
index 21786a7..86e4bab 100644 (file)
@@ -301,6 +301,19 @@ the value, the less precise the timestamp.
 <li><b>$Sleep</b> &lt;seconds&gt; - puts the rsyslog main thread to sleep for the specified
 number of seconds immediately when the directive is encountered. You should have a
 good reason for using this directive!</li>
+<li><b>$LocalHostIPIF</b>  &lt;interface name&gt; - (available since 5.9.6) - if provided, the IP of the specified
+interface (e.g. "eth0") shall be used as fromhost-ip for locall-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. Note that this directive can be given only
+once. Trying to reset will result in an error message and the new value will
+be ignored. Please note that modules must have support for obtaining the local
+IP address set via this directive. While this is the case for rsyslog-provided
+modules, it may not always be the case for contributed plugins.
+<br><b>Important:</b> This directive shall be placed <b>right at the top of
+rsyslog.conf</b>. Otherwise, if error messages are triggered before this directive
+is processed, rsyslog will fix the local host IP to "127.0.0.1", what than can
+not be reset.
+</li>
 <li><a href="rsconf1_umask.html">$UMASK</a></li>
 </ul>
 <p><b>Where &lt;size_nbr&gt; is specified above,</b>
index 3012136..ba497e0 100644 (file)
@@ -62,7 +62,6 @@ typedef struct configSettings_s {
 static configSettings_t cs;
 
 static prop_t *pInputName = NULL;
-static prop_t *pLocalHostIP = NULL;
 
 BEGINisCompatibleWithFeature
 CODESTARTisCompatibleWithFeature
@@ -92,7 +91,7 @@ doSubmitMsg(uchar *line)
        MsgSetRawMsgWOSize(pMsg, (char*)line);
        MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
        MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
-       MsgSetRcvFromIP(pMsg, pLocalHostIP);
+       MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP());
        MsgSetMSGoffs(pMsg, 0);
        MsgSetTAG(pMsg, UCHAR_CONSTANT("rsyslogd-pstats:"), sizeof("rsyslogd-pstats:") - 1);
        pMsg->iFacility = cs.iFacility;
@@ -169,7 +168,6 @@ ENDafterRun
 BEGINmodExit
 CODESTARTmodExit
        prop.Destruct(&pInputName);
-       prop.Destruct(&pLocalHostIP);
        /* release objects we used */
        objRelease(glbl, CORE_COMPONENT);
        objRelease(prop, CORE_COMPONENT);
@@ -212,10 +210,6 @@ CODEmodInit_QueryRegCFSLineHdlr
        CHKiRet(prop.Construct(&pInputName));
        CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("impstats"), sizeof("impstats") - 1));
        CHKiRet(prop.ConstructFinalize(pInputName));
-
-       CHKiRet(prop.Construct(&pLocalHostIP));
-       CHKiRet(prop.SetString(pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
-       CHKiRet(prop.ConstructFinalize(pLocalHostIP));
 ENDmodInit
 /* vi:set ai:
  */
index dea5a17..134e6c6 100644 (file)
@@ -7,25 +7,23 @@
  *
  * Module begun 2008-04-16 by Rainer Gerhards
  *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2008-2012 Rainer Gerhards and Adiscon GmbH.
  *
  * This file is part of the rsyslog runtime library.
  *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library.  If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *       -or-
+ *       see COPYING.ASL20 in the source distribution
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include "config.h"
@@ -44,6 +42,7 @@
 #include "prop.h"
 #include "atomic.h"
 #include "errmsg.h"
+#include "net.h"
 
 /* some defaults */
 #ifndef DFLT_NETSTRM_DRVR
@@ -54,6 +53,7 @@
 DEFobjStaticHelpers
 DEFobjCurrIf(prop)
 DEFobjCurrIf(errmsg)
+DEFobjCurrIf(net)
 
 /* static data
  * For this object, these variables are obviously what makes the "meat" of the
@@ -68,6 +68,7 @@ static int iDefPFFamily = PF_UNSPEC;     /* protocol family (IPv4, IPv6 or both)
 static int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
 static int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
 static int bDisableDNS = 0; /* don't look up IP addresses of remote messages */
+static prop_t *propLocalIPIF = NULL;/* IP address to report for the local host (default is 127.0.0.1) */
 static prop_t *propLocalHostName = NULL;/* our hostname as FQDN - read-only after startup */
 static uchar *LocalHostName = NULL;/* our hostname  - read-only after startup */
 static uchar *LocalHostNameOverride = NULL;/* user-overridden hostname - read-only after startup */
@@ -152,6 +153,60 @@ static void SetGlobalInputTermination(void)
 }
 
 
+/* set the local host IP address to a specific string. Helper to
+ * small set of functions. No checks done, caller must ensure it is
+ * ok to call. Most importantly, the IP address must not already have 
+ * been set. -- rgerhards, 2012-03-21
+ */
+static inline rsRetVal
+storeLocalHostIPIF(uchar *myIP)
+{
+       DEFiRet;
+       CHKiRet(prop.Construct(&propLocalIPIF));
+       CHKiRet(prop.SetString(propLocalIPIF, myIP, ustrlen(myIP)));
+       CHKiRet(prop.ConstructFinalize(propLocalIPIF));
+       DBGPRINTF("rsyslog/glbl: using '%s' as localhost IP\n", myIP);
+finalize_it:
+       RETiRet;
+}
+
+
+/* This function is used to set the IP address that is to be
+ * reported for the local host. Note that in order to ease things
+ * for the v6 config interface, we do not allow to set this more
+ * than once.
+ * rgerhards, 2012-03-21
+ */
+static rsRetVal
+setLocalHostIPIF(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+       uchar myIP[128];
+       rsRetVal localRet;
+       DEFiRet;
+
+       CHKiRet(objUse(net, CORE_COMPONENT));
+
+       if(propLocalIPIF != NULL) {
+               errmsg.LogError(0, RS_RET_ERR, "$LocalHostIPIF is already set "
+                               "and cannot be reset; place it at TOP OF rsyslog.conf!");
+               ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
+       }
+
+       localRet = net.GetIFIPAddr(pNewVal, AF_UNSPEC, myIP, (int) sizeof(myIP));
+       if(localRet != RS_RET_OK) {
+               errmsg.LogError(0, RS_RET_ERR, "$LocalIPIF: IP address for interface "
+                               "'%s' cannnot be obtained - ignoring directive", pNewVal);
+       } else  {
+               storeLocalHostIPIF(myIP);
+       }
+
+
+finalize_it:
+       free(pNewVal); /* no longer needed -> is in prop! */
+       RETiRet;
+}
+
+
 /* This function is used to set the global work directory name. 
  * It verifies that the provided directory actually exists and
  * emits an error message if not.
@@ -202,6 +257,22 @@ finalize_it:
        RETiRet;
 }
 
+/* return our local IP.
+ * If no local IP is set, "127.0.0.1" is selected *and* set. This
+ * is an intensional side effect that we do in order to keep things
+ * consistent and avoid config errors (this will make us not accept
+ * setting the local IP address once a module has obtained it - so
+ * it forces the $LocalHostIPIF directive high up in rsyslog.conf)
+ * rgerhards, 2012-03-21
+ */
+static prop_t*
+GetLocalHostIP(void)
+{
+       if(propLocalIPIF == NULL)
+               storeLocalHostIPIF((uchar*)"127.0.0.1");
+       return(propLocalIPIF);
+}
+
 /* return our local hostname. if it is not set, "[localhost]" is returned
  */
 static uchar*
@@ -338,6 +409,7 @@ CODESTARTobjQueryInterface(glbl)
        pIf->GetWorkDir = GetWorkDir;
        pIf->GenerateLocalHostNameProperty = GenerateLocalHostNameProperty;
        pIf->GetLocalHostNameProp = GetLocalHostNameProp;
+       pIf->GetLocalHostIP = GetLocalHostIP;
        pIf->SetGlobalInputTermination = SetGlobalInputTermination;
        pIf->GetGlobalInputTermState = GetGlobalInputTermState;
 #define SIMP_PROP(name) \
@@ -417,7 +489,7 @@ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
        CHKiRet(objUse(prop, CORE_COMPONENT));
        CHKiRet(objUse(errmsg, CORE_COMPONENT));
 
-       /* register config handlers (TODO: we need to implement a way to unregister them) */
+       /* config handlers are never unregistered and need not be - we are always loaded ;) */
        CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, setWorkDir, NULL, NULL));
        CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL));
        CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvr, NULL));
@@ -425,6 +497,7 @@ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
        CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrKeyFile, NULL));
        CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCertFile, NULL));
        CHKiRet(regCfSysLineHdlr((uchar *)"localhostname", 0, eCmdHdlrGetWord, NULL, &LocalHostNameOverride, NULL));
+       CHKiRet(regCfSysLineHdlr((uchar *)"localhostipif", 0, eCmdHdlrGetWord, setLocalHostIPIF, NULL, NULL));
        CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrBinary, NULL, &bOptimizeUniProc, NULL));
        CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL));
        CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL));
@@ -437,21 +510,14 @@ ENDObjClassInit(glbl)
  * rgerhards, 2008-04-17
  */
 BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */
-       if(pszDfltNetstrmDrvr != NULL)
-               free(pszDfltNetstrmDrvr);
-       if(pszDfltNetstrmDrvrCAF != NULL)
-               free(pszDfltNetstrmDrvrCAF);
-       if(pszDfltNetstrmDrvrKeyFile != NULL)
-               free(pszDfltNetstrmDrvrKeyFile);
-       if(pszDfltNetstrmDrvrCertFile != NULL)
-               free(pszDfltNetstrmDrvrCertFile);
-       if(pszWorkDir != NULL)
-               free(pszWorkDir);
-       if(LocalHostName != NULL)
-               free(LocalHostName);
+       free(pszDfltNetstrmDrvr);
+       free(pszDfltNetstrmDrvrCAF);
+       free(pszDfltNetstrmDrvrKeyFile);
+       free(pszDfltNetstrmDrvrCertFile);
+       free(pszWorkDir);
+       free(LocalHostName);
        free(LocalHostNameOverride);
-       if(LocalFQDNName != NULL)
-               free(LocalFQDNName);
+       free(LocalFQDNName);
        objRelease(prop, CORE_COMPONENT);
        DESTROY_ATOMIC_HELPER_MUT(mutTerminateInputs);
 ENDObjClassExit(glbl)
index 4b4bdf8..3c5e850 100644 (file)
@@ -8,25 +8,23 @@
  * Please note that there currently is no glbl.c file as we do not yet
  * have any implementations.
  *
- * Copyright 2008, 2009 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2008-2012 Rainer Gerhards and Adiscon GmbH.
  *
  * This file is part of the rsyslog runtime library.
  *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library.  If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *       -or-
+ *       see COPYING.ASL20 in the source distribution
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #ifndef GLBL_H_INCLUDED
@@ -77,6 +75,8 @@ BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */
        SIMP_PROP(FdSetSize, int)
        /* v7: was neeeded to mean v5+v6 - do NOT add anything else for that version! */
        /* next change is v8! */
+       /* v8 - 2012-03-21 */
+       prop_t* (*GetLocalHostIP)(void);
 #undef SIMP_PROP
 ENDinterface(glbl)
 #define glblCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */
index 02a0dad..9cd3c9c 100644 (file)
@@ -199,7 +199,6 @@ static rsRetVal GlobalClassExit(void);
 #endif
 
 static prop_t *pInternalInputName = NULL;      /* there is only one global inputName for all internally-generated messages */
-static prop_t *pLocalHostIP = NULL;            /* there is only one global IP for all internally-generated messages */
 static uchar   *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */
 static char    *PidFile = _PATH_LOGPID; /* read-only after startup */
 
@@ -545,7 +544,8 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags)
        MsgSetRawMsgWOSize(pMsg, (char*)msg);
        MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
        MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
-       MsgSetRcvFromIP(pMsg, pLocalHostIP);
+dbgprintf("ZZZZ: pLocalHostIPIF used!\n");
+       MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP());
        MsgSetMSGoffs(pMsg, 0);
        /* check if we have an error code associated and, if so,
         * adjust the tag. -- rgerhards, 2008-06-27
@@ -1109,8 +1109,6 @@ die(int sig)
        /* destruct our global properties */
        if(pInternalInputName != NULL)
                prop.Destruct(&pInternalInputName);
-       if(pLocalHostIP != NULL)
-               prop.Destruct(&pLocalHostIP);
 
        /* terminate the remaining classes */
        GlobalClassExit();
@@ -2660,10 +2658,6 @@ int realMain(int argc, char **argv)
        CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslgod") - 1));
        CHKiRet(prop.ConstructFinalize(pInternalInputName));
 
-       CHKiRet(prop.Construct(&pLocalHostIP));
-       CHKiRet(prop.SetString(pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
-       CHKiRet(prop.ConstructFinalize(pLocalHostIP));
-
        /* get our host and domain names - we need to do this early as we may emit
         * error log messages, which need the correct hostname. -- rgerhards, 2008-04-04
         */
@@ -2712,7 +2706,6 @@ 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, '.')))