bugfix: hostname was not requeried on HUP

Thanks to Marius Tomaschewski for reporting this bug.
This commit is contained in:
Rainer Gerhards 2012-04-11 11:18:41 +02:00
parent eef1701be2
commit d0a73d3449
5 changed files with 161 additions and 125 deletions

View File

@ -1,4 +1,8 @@
---------------------------------------------------------------------------
Version 5.8.11 [V5-stable] 2012-04-??
- bugfix: hostname was not requeried on HUP
Thanks to Marius Tomaschewski for reporting this bug.
---------------------------------------------------------------------------
Version 5.8.10 [V5-stable] 2012-04-05
- bugfix: segfault on startup if $actionqueuefilename was missing for disk
queue config

View File

@ -152,15 +152,6 @@ our paper on <a href="multi_ruleset.html">using multiple rule sets in rsyslog</a
<li><a href="rsconf1_gssforwardservicename.html">$GssForwardServiceName</a></li>
<li><a href="rsconf1_gsslistenservicename.html">$GssListenServiceName</a></li>
<li><a href="rsconf1_gssmode.html">$GssMode</a></li>
<li>$HUPisRestart [on/<b>off</b>] - if set to on, a HUP is a full daemon restart. This means any queued messages are discarded (depending
on queue configuration, of course) all modules are unloaded and reloaded. This mode keeps compatible with sysklogd, but is
not recommended for use with rsyslog. To do a full restart, simply stop and start the daemon. The default (since 4.5.1) is "off".
If it is set to "off", a HUP will only close open files. This is a much quicker action and usually
the only one that is needed e.g. for log rotation. <b>Restart-type HUPs (value "on") are depricated</b>
and will go away in rsyslog v5. So it is a good idea to change anything that needs it, now.
Usually that should not be a big issue, as the restart-type HUP can easily be replaced by
something along the lines of &quot;/etc/init.d/rsyslog restart&quot;.
</li>
<li><a href="rsconf1_includeconfig.html">$IncludeConfig</a></li><li>MainMsgQueueCheckpointInterval &lt;number&gt;</li>
<li><b>$LocalHostName</b> [name] - this directive permits to overwrite the system
hostname with the one specified in the directive. If the directive is given

View File

@ -16,6 +16,7 @@ available. This processing was redundant and had a lot a drawbacks.
For details, please see the
<a href="v4compatibility.html">rsyslog v4 compatibility notes</a> which elaborate
on the reasons and the (few) things you may need to change.
<p>Please note that starting with 5.8.11 HUP will also requery the local hostname.
<h2>Queue on-disk format</h2>
<p>The queue information file format has been changed. When upgrading from v4 to
v5, make sure that the queue is emptied and no on-disk structure present. We did

View File

@ -69,10 +69,10 @@ static int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records
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 *propLocalHostName = NULL;/* our hostname as FQDN - read-only after startup */
static uchar *LocalHostName = NULL;/* our hostname - read-only after startup */
static uchar *LocalHostName = NULL;/* our hostname - read-only after startup, except HUP */
static uchar *LocalHostNameOverride = NULL;/* user-overridden hostname - read-only after startup */
static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup */
static uchar *LocalDomain; /* our local domain name - read-only after startup */
static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup, except HUP */
static uchar *LocalDomain = NULL;/* our local domain name - read-only after startup, except HUP */
static char **StripDomains = NULL;/* these domains may be stripped before writing logs - r/o after s.u., never touched by init */
static char **LocalHosts = NULL;/* these hosts are logged with their hostname - read-only after startup, never touched by init */
static uchar *pszDfltNetstrmDrvr = NULL; /* module name of default netstream driver */
@ -115,15 +115,12 @@ SIMP_PROP(DefPFFamily, iDefPFFamily, int) /* note that in the future we may chec
SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int)
SIMP_PROP(Option_DisallowWarning, option_DisallowWarning, int)
SIMP_PROP(DisableDNS, bDisableDNS, int)
SIMP_PROP(LocalDomain, LocalDomain, uchar*)
SIMP_PROP(StripDomains, StripDomains, char**)
SIMP_PROP(LocalHosts, LocalHosts, char**)
#ifdef USE_UNLIMITED_SELECT
SIMP_PROP(FdSetSize, iFdSetSize, int)
#endif
SIMP_PROP_SET(LocalFQDNName, LocalFQDNName, uchar*)
SIMP_PROP_SET(LocalHostName, LocalHostName, uchar*)
SIMP_PROP_SET(DfltNetstrmDrvr, pszDfltNetstrmDrvr, uchar*) /* TODO: use custom function which frees existing value */
SIMP_PROP_SET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar*) /* TODO: use custom function which frees existing value */
SIMP_PROP_SET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar*) /* TODO: use custom function which frees existing value */
@ -202,6 +199,19 @@ finalize_it:
RETiRet;
}
/* set our local hostname. Free previous hostname, if it was already set.
* Note that we do now do this in a thread
* "once in a lifetime" action which can not be undone. -- gerhards, 2009-07-20
*/
static rsRetVal
SetLocalHostName(uchar *newname)
{
free(LocalHostName);
LocalHostName = newname;
return RS_RET_OK;
}
/* return our local hostname. if it is not set, "[localhost]" is returned
*/
static uchar*
@ -227,6 +237,26 @@ done:
}
/* set our local domain name. Free previous domain, if it was already set.
*/
static rsRetVal
SetLocalDomain(uchar *newname)
{
free(LocalDomain);
LocalDomain = newname;
return RS_RET_OK;
}
/* return our local hostname. if it is not set, "[localhost]" is returned
*/
static uchar*
GetLocalDomain(void)
{
return LocalDomain;
}
/* generate the local hostname property. This must be done after the hostname info
* has been set as well as PreserveFQDN.
* rgerhards, 2009-06-30
@ -271,6 +301,14 @@ GetLocalHostNameProp(void)
}
static rsRetVal
SetLocalFQDNName(uchar *newname)
{
free(LocalFQDNName);
LocalFQDNName = newname;
return RS_RET_OK;
}
/* return the current localhost name as FQDN (requires FQDN to be set)
* TODO: we should set the FQDN ourselfs in here!
*/
@ -373,30 +411,18 @@ ENDobjQueryInterface(glbl)
*/
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
if(pszDfltNetstrmDrvr != NULL) {
free(pszDfltNetstrmDrvr);
pszDfltNetstrmDrvr = NULL;
}
if(pszDfltNetstrmDrvrCAF != NULL) {
free(pszDfltNetstrmDrvrCAF);
pszDfltNetstrmDrvrCAF = NULL;
}
if(pszDfltNetstrmDrvrKeyFile != NULL) {
free(pszDfltNetstrmDrvrKeyFile);
pszDfltNetstrmDrvrKeyFile = NULL;
}
if(pszDfltNetstrmDrvrCertFile != NULL) {
free(pszDfltNetstrmDrvrCertFile);
pszDfltNetstrmDrvrCertFile = NULL;
}
if(LocalHostNameOverride != NULL) {
free(LocalHostNameOverride);
LocalHostNameOverride = NULL;
}
if(pszWorkDir != NULL) {
free(pszWorkDir);
pszWorkDir = NULL;
}
free(pszDfltNetstrmDrvr);
pszDfltNetstrmDrvr = NULL;
free(pszDfltNetstrmDrvrCAF);
pszDfltNetstrmDrvrCAF = NULL;
free(pszDfltNetstrmDrvrKeyFile);
pszDfltNetstrmDrvrKeyFile = NULL;
free(pszDfltNetstrmDrvrCertFile);
pszDfltNetstrmDrvrCertFile = NULL;
free(LocalHostNameOverride);
LocalHostNameOverride = NULL;
free(pszWorkDir);
pszWorkDir = NULL;
bDropMalPTRMsgs = 0;
bOptimizeUniProc = 1;
bPreserveFQDN = 0;
@ -437,21 +463,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)

View File

@ -154,6 +154,7 @@ DEFobjCurrIf(net) /* TODO: make go away! */
/* forward definitions */
static rsRetVal GlobalClassExit(void);
static rsRetVal queryLocalHostname(void);
#ifndef _PATH_LOGCONF
@ -1897,6 +1898,11 @@ DEFFUNC_llExecFunc(doHUPActions)
* is *NOT* the sighup handler. The signal is recorded by the handler, that record
* detected inside the mainloop and then this function is called to do the
* real work. -- rgerhards, 2008-10-22
* Note: there is a VERY slim chance of a data race when the hostname is reset.
* We prefer to take this risk rather than sync all accesses, because to the best
* of my analysis it can not really hurt (the actual property is reference-counted)
* but the sync would require some extra CPU for *each* message processed.
* rgerhards, 2012-04-11
*/
static inline void
doHUP(void)
@ -1912,6 +1918,7 @@ doHUP(void)
logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
}
queryLocalHostname(); /* re-read our name */
ruleset.IterateAllActions(doHUPActions, NULL);
}
@ -2329,6 +2336,90 @@ GlobalClassExit(void)
}
/* query our host and domain names - we need to do this early as we may emit
* rgerhards, 2012-04-11
*/
static rsRetVal
queryLocalHostname(void)
{
uchar *LocalHostName;
uchar *LocalDomain;
uchar *LocalFQDNName;
uchar *p;
struct hostent *hent;
DEFiRet;
net.getLocalHostname(&LocalFQDNName);
CHKmalloc(LocalHostName = (uchar*) strdup((char*)LocalFQDNName));
glbl.SetLocalFQDNName(LocalFQDNName); /* set the FQDN before we modify it */
if((p = (uchar*)strchr((char*)LocalHostName, '.'))) {
*p++ = '\0';
LocalDomain = p;
} else {
LocalDomain = (uchar*)"";
/* It's not clearly defined whether gethostname()
* should return the simple hostname or the fqdn. A
* good piece of software should be aware of both and
* we want to distribute good software. Joey
*
* Good software also always checks its return values...
* If syslogd starts up before DNS is up & /etc/hosts
* doesn't have LocalHostName listed, gethostbyname will
* return NULL.
*/
/* TODO: gethostbyname() is not thread-safe, but replacing it is
* not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25
*/
hent = gethostbyname((char*)LocalHostName);
if(hent) {
int i = 0;
if(hent->h_aliases) {
size_t hnlen;
hnlen = strlen((char *) LocalHostName);
for (i = 0; hent->h_aliases[i]; i++) {
if (!strncmp(hent->h_aliases[i], (char *) LocalHostName, hnlen)
&& hent->h_aliases[i][hnlen] == '.') {
/* found a matching hostname */
break;
}
}
}
free(LocalHostName);
if(hent->h_aliases && hent->h_aliases[i]) {
CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_aliases[i]));
} else {
CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_name));
}
if((p = (uchar*)strchr((char*)LocalHostName, '.')))
{
*p++ = '\0';
LocalDomain = p;
}
}
}
/* Convert to lower case to recognize the correct domain laterly */
for(p = LocalDomain ; *p ; p++)
*p = (char)tolower((int)*p);
/* we now have our hostname and can set it inside the global vars.
* TODO: think if all of this would better be a runtime function
* rgerhards, 2008-04-17
*/
glbl.SetLocalHostName(LocalHostName);
glbl.SetLocalDomain(LocalDomain);
glbl.GenerateLocalHostNameProperty(); /* must be redone after conf processing, FQDN setting may have changed */
finalize_it:
RETiRet;
}
/* some support for command line option parsing. Any non-trivial options must be
* buffered until the complete command line has been parsed. This is necessary to
* prevent dependencies between the options. That, in turn, means we need to have
@ -2530,9 +2621,7 @@ int realMain(int argc, char **argv)
{
DEFiRet;
register uchar *p;
int ch;
struct hostent *hent;
extern int optind;
extern char *optarg;
int bEOptionWasGiven = 0;
@ -2541,9 +2630,6 @@ int realMain(int argc, char **argv)
int bChDirRoot = 1; /* change the current working directory to "/"? */
char *arg; /* for command line option processing */
uchar legacyConfLine[80];
uchar *LocalHostName;
uchar *LocalDomain;
uchar *LocalFQDNName;
char cwdbuf[128]; /* buffer to obtain/display current working directory */
/* first, parse the command line options. We do not carry out any actual work, just
@ -2651,7 +2737,7 @@ int realMain(int argc, char **argv)
/* we need to create the inputName property (only once during our lifetime) */
CHKiRet(prop.Construct(&pInternalInputName));
CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslgod") - 1));
CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd") - 1));
CHKiRet(prop.ConstructFinalize(pInternalInputName));
CHKiRet(prop.Construct(&pLocalHostIP));
@ -2661,72 +2747,7 @@ int realMain(int argc, char **argv)
/* 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
*/
net.getLocalHostname(&LocalFQDNName);
CHKmalloc(LocalHostName = (uchar*) strdup((char*)LocalFQDNName));
glbl.SetLocalFQDNName(LocalFQDNName); /* set the FQDN before we modify it */
if((p = (uchar*)strchr((char*)LocalHostName, '.'))) {
*p++ = '\0';
LocalDomain = p;
} else {
LocalDomain = (uchar*)"";
/* It's not clearly defined whether gethostname()
* should return the simple hostname or the fqdn. A
* good piece of software should be aware of both and
* we want to distribute good software. Joey
*
* Good software also always checks its return values...
* If syslogd starts up before DNS is up & /etc/hosts
* doesn't have LocalHostName listed, gethostbyname will
* return NULL.
*/
/* TODO: gethostbyname() is not thread-safe, but replacing it is
* not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25
*/
hent = gethostbyname((char*)LocalHostName);
if(hent) {
int i = 0;
if(hent->h_aliases) {
size_t hnlen;
hnlen = strlen((char *) LocalHostName);
for (i = 0; hent->h_aliases[i]; i++) {
if (!strncmp(hent->h_aliases[i], (char *) LocalHostName, hnlen)
&& hent->h_aliases[i][hnlen] == '.') {
/* found a matching hostname */
break;
}
}
}
free(LocalHostName);
if(hent->h_aliases && hent->h_aliases[i]) {
CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_aliases[i]));
} else {
CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_name));
}
if((p = (uchar*)strchr((char*)LocalHostName, '.')))
{
*p++ = '\0';
LocalDomain = p;
}
}
}
/* Convert to lower case to recognize the correct domain laterly */
for(p = LocalDomain ; *p ; p++)
*p = (char)tolower((int)*p);
/* we now have our hostname and can set it inside the global vars.
* TODO: think if all of this would better be a runtime function
* rgerhards, 2008-04-17
*/
glbl.SetLocalHostName(LocalHostName);
glbl.SetLocalDomain(LocalDomain);
glbl.GenerateLocalHostNameProperty(); /* must be redone after conf processing, FQDN setting may have changed */
queryLocalHostname();
/* initialize the objects */
if((iRet = modInitIminternal()) != RS_RET_OK) {