diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2013-01-22 16:55:21 +0100 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2013-01-22 16:55:21 +0100 |
commit | 35bec820b601bfcf9eff314fbfc718bb8949bda1 (patch) | |
tree | e67ec971d8d89df26727330e527df955535410f3 | |
parent | 45d11af0b9975937e536d1c9b6d7bdaff5ade1b0 (diff) | |
download | rsyslog-35bec820b601bfcf9eff314fbfc718bb8949bda1.tar.gz rsyslog-35bec820b601bfcf9eff314fbfc718bb8949bda1.tar.bz2 rsyslog-35bec820b601bfcf9eff314fbfc718bb8949bda1.zip |
optimze: reduce memory operations during dns resolution/hostname setting
previously, hostname and ip strings were shuffled to the msg object, which
created a property out of them. Now the cache holds the property, and it
is resused (almost) everywhere, what saves a lot of memory operations.
The only exception is imtcp session setup, where different handling
of the hostname is done, which we need to sort out (but that's another
story).
-rw-r--r-- | runtime/dnscache.c | 100 | ||||
-rw-r--r-- | runtime/dnscache.h | 2 | ||||
-rw-r--r-- | runtime/msg.c | 58 | ||||
-rw-r--r-- | runtime/net.c | 86 | ||||
-rw-r--r-- | runtime/net.h | 2 | ||||
-rw-r--r-- | runtime/nsd_ptcp.c | 2 | ||||
-rw-r--r-- | runtime/prop.c | 7 | ||||
-rw-r--r-- | tools/syslogd.c | 12 |
8 files changed, 145 insertions, 124 deletions
diff --git a/runtime/dnscache.c b/runtime/dnscache.c index ef168f23..2096aa36 100644 --- a/runtime/dnscache.c +++ b/runtime/dnscache.c @@ -50,6 +50,7 @@ struct dnscache_entry_s { struct sockaddr_storage addr; prop_t *fqdn; prop_t *fqdnLowerCase; + prop_t *localName; /* only local name, without domain part (if configured so) */ prop_t *ip; struct dnscache_entry_s *next; unsigned nUsed; @@ -106,6 +107,8 @@ entryDestruct(dnscache_entry_t *etry) prop.Destruct(&etry->fqdn); if(etry->fqdnLowerCase != NULL) prop.Destruct(&etry->fqdnLowerCase); + if(etry->localName != NULL) + prop.Destruct(&etry->localName); if(etry->ip != NULL) prop.Destruct(&etry->ip); free(etry); @@ -177,6 +180,73 @@ mygetnameinfo(const struct sockaddr *sa, socklen_t salen, } +/* get only the local part of the hostname and set it in cache entry */ +static inline void +setLocalHostName(dnscache_entry_t *etry) +{ + uchar *fqdnLower; + uchar *p; + int count; + int i; + uchar hostbuf[NI_MAXHOST]; + + if(glbl.GetPreserveFQDN()) { + prop.AddRef(etry->fqdnLowerCase); + etry->localName = etry->fqdnLowerCase; + goto done; + } + + /* strip domain, if configured for this entry */ + fqdnLower = propGetSzStr(etry->fqdnLowerCase); + p = (uchar*)strchr((char*)fqdnLower, '.'); /* find start of domain name "machine.example.com" */ + if(p == NULL) { /* do we have a domain part? */ + prop.AddRef(etry->fqdnLowerCase); /* no! */ + etry->localName = etry->fqdnLowerCase; + goto done; + } + + i = p - fqdnLower; /* length of hostname */ + memcpy(hostbuf, fqdnLower, i); + /* now check if we belong to any of the domain names that were specified + * in the -s command line option. If so, remove and we are done. + */ + if(glbl.GetStripDomains() != NULL) { + count=0; + while(glbl.GetStripDomains()[count]) { + if(strcmp((char*)(p + 1), glbl.GetStripDomains()[count]) == 0) { + prop.CreateStringProp(&etry->localName, hostbuf, i); + goto done; + } + count++; + } + } + /* if we reach this point, we have not found any domain we should strip. Now + * we try and see if the host itself is listed in the -l command line option + * and so should be stripped also. If so, we do it and return. Please note that + * -l list FQDNs, not just the hostname part. If it did just list the hostname, the + * door would be wide-open for all kinds of mixing up of hosts. Because of this, + * you'll see comparison against the full string (pszHostFQDN) below. + */ + if(glbl.GetLocalHosts() != NULL) { + count=0; + while(glbl.GetLocalHosts()[count]) { + if(!strcmp((char*)fqdnLower, (char*)glbl.GetLocalHosts()[count])) { + prop.CreateStringProp(&etry->localName, hostbuf, i); + goto done; + } + count++; + } + } + + /* at this point, we have not found anything, so we again use the + * already-created complete full name property. + */ + prop.AddRef(etry->fqdnLowerCase); + etry->localName = etry->fqdnLowerCase; +done: return; +} + + /* resolve an address. * * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats) @@ -187,7 +257,7 @@ mygetnameinfo(const struct sockaddr *sa, socklen_t salen, * message should be processed (1) or discarded (0). */ static rsRetVal -resolveAddr(struct sockaddr_storage *addr, prop_t **fqdn, prop_t **fqdnLowerCase, prop_t **ip) +resolveAddr(struct sockaddr_storage *addr, dnscache_entry_t *etry) { DEFiRet; int error; @@ -258,10 +328,10 @@ resolveAddr(struct sockaddr_storage *addr, prop_t **fqdn, prop_t **fqdnLowerCase error = 1; /* that will trigger using IP address below. */ } else {/* we have a valid entry, so let's create the respective properties */ fqdnLen = strlen(fqdnBuf); - prop.CreateStringProp(fqdn, (uchar*)fqdnBuf, fqdnLen); + prop.CreateStringProp(&etry->fqdn, (uchar*)fqdnBuf, fqdnLen); for(i = 0 ; i < fqdnLen ; ++i) fqdnBuf[i] = tolower(fqdnBuf[i]); - prop.CreateStringProp(fqdnLowerCase, (uchar*)fqdnBuf, fqdnLen); + prop.CreateStringProp(&etry->fqdnLowerCase, (uchar*)fqdnBuf, fqdnLen); } } pthread_sigmask(SIG_SETMASK, &omask, NULL); @@ -275,16 +345,18 @@ finalize_it: } /* we need to create the inputName property (only once during our lifetime) */ - prop.CreateStringProp(ip, (uchar*)szIP, strlen(szIP)); + prop.CreateStringProp(&etry->ip, (uchar*)szIP, strlen(szIP)); if(error || glbl.GetDisableDNS()) { dbgprintf("Host name for your address (%s) unknown\n", szIP); - prop.AddRef(*ip); - *fqdn = *ip; - prop.AddRef(*ip); - *fqdnLowerCase = *ip; + prop.AddRef(etry->ip); + etry->fqdn = etry->ip; + prop.AddRef(etry->ip); + etry->fqdnLowerCase = etry->ip; } + setLocalHostName(etry); + RETiRet; } @@ -298,7 +370,7 @@ addEntry(struct sockaddr_storage *addr, dnscache_entry_t **pEtry) DEFiRet; CHKmalloc(etry = MALLOC(sizeof(dnscache_entry_t))); - CHKiRet(resolveAddr(addr, &etry->fqdn, &etry->fqdnLowerCase, &etry->ip)); + CHKiRet(resolveAddr(addr, etry)); memcpy(&etry->addr, addr, SALEN((struct sockaddr*) addr)); etry->nUsed = 0; *pEtry = etry; @@ -342,7 +414,7 @@ validateEntry(dnscache_entry_t __attribute__((unused)) *etry, struct sockaddr_st */ rsRetVal dnscacheLookup(struct sockaddr_storage *addr, prop_t **fqdn, prop_t **fqdnLowerCase, - prop_t **ip) + prop_t **localName, prop_t **ip) { dnscache_entry_t *etry; DEFiRet; @@ -365,6 +437,10 @@ dnscacheLookup(struct sockaddr_storage *addr, prop_t **fqdn, prop_t **fqdnLowerC prop.AddRef(etry->fqdnLowerCase); *fqdnLowerCase = etry->fqdnLowerCase; } + if(localName != NULL) { + prop.AddRef(etry->localName); + *localName = etry->localName; + } finalize_it: pthread_rwlock_unlock(&dnsCache.rwlock); @@ -380,6 +456,10 @@ finalize_it: prop.AddRef(staticErrValue); *fqdnLowerCase = staticErrValue; } + if(localName != NULL) { + prop.AddRef(staticErrValue); + *localName = staticErrValue; + } } RETiRet; } diff --git a/runtime/dnscache.h b/runtime/dnscache.h index 7113c942..9c21a645 100644 --- a/runtime/dnscache.h +++ b/runtime/dnscache.h @@ -24,6 +24,6 @@ rsRetVal dnscacheInit(void); rsRetVal dnscacheDeinit(void); -rsRetVal dnscacheLookup(struct sockaddr_storage *addr, prop_t **fqdn, prop_t **fqdnLowerCase, prop_t **ip); +rsRetVal dnscacheLookup(struct sockaddr_storage *addr, prop_t **fqdn, prop_t **fqdnLowerCase, prop_t **localName, prop_t **ip); #endif /* #ifndef INCLUDED_DNSCACHE_H */ diff --git a/runtime/msg.c b/runtime/msg.c index 86c2e68c..68577ad0 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -337,6 +337,37 @@ MsgUnlock(msg_t *pThis) } +/* set RcvFromIP name in msg object WITHOUT calling AddRef. + * rgerhards, 2013-01-22 + */ +static inline void +MsgSetRcvFromIPWithoutAddRef(msg_t *pThis, prop_t *new) +{ + if(pThis->pRcvFromIP != NULL) + prop.Destruct(&pThis->pRcvFromIP); + pThis->pRcvFromIP = new; +} + + +/* set RcvFrom name in msg object WITHOUT calling AddRef. + * rgerhards, 2013-01-22 + */ +void MsgSetRcvFromWithoutAddRef(msg_t *pThis, prop_t *new) +{ + assert(pThis != NULL); + + if(pThis->msgFlags & NEEDS_DNSRESOL) { + if(pThis->rcvFrom.pfrominet != NULL) + free(pThis->rcvFrom.pfrominet); + pThis->msgFlags &= ~NEEDS_DNSRESOL; + } else { + if(pThis->rcvFrom.pRcvFrom != NULL) + prop.Destruct(&pThis->rcvFrom.pRcvFrom); + } + pThis->rcvFrom.pRcvFrom = new; +} + + /* rgerhards 2012-04-18: set associated ruleset (by ruleset name) * If ruleset cannot be found, no update is done. */ @@ -361,18 +392,17 @@ resolveDNS(msg_t *pMsg) { rsRetVal localRet; prop_t *propFromHost = NULL; prop_t *ip; - uchar fromHost[NI_MAXHOST]; - uchar fromHostFQDN[NI_MAXHOST]; + prop_t *localName; DEFiRet; MsgLock(pMsg); CHKiRet(objUse(net, CORE_COMPONENT)); if(pMsg->msgFlags & NEEDS_DNSRESOL) { - localRet = net.cvthname(pMsg->rcvFrom.pfrominet, fromHost, fromHostFQDN, - &ip); + localRet = net.cvthname(pMsg->rcvFrom.pfrominet, &localName, NULL, &ip); if(localRet == RS_RET_OK) { - MsgSetRcvFromStr(pMsg, fromHost, ustrlen(fromHost), &propFromHost); - CHKiRet(MsgSetRcvFromIP(pMsg, ip)); + /* we pass down the props, so no need for AddRef */ + MsgSetRcvFromWithoutAddRef(pMsg, localName); + MsgSetRcvFromIPWithoutAddRef(pMsg, ip); } } finalize_it: @@ -2207,18 +2237,8 @@ finalize_it: */ void MsgSetRcvFrom(msg_t *pThis, prop_t *new) { - assert(pThis != NULL); - prop.AddRef(new); - if(pThis->msgFlags & NEEDS_DNSRESOL) { - if(pThis->rcvFrom.pfrominet != NULL) - free(pThis->rcvFrom.pfrominet); - pThis->msgFlags &= ~NEEDS_DNSRESOL; - } else { - if(pThis->rcvFrom.pRcvFrom != NULL) - prop.Destruct(&pThis->rcvFrom.pRcvFrom); - } - pThis->rcvFrom.pRcvFrom = new; + MsgSetRcvFromWithoutAddRef(pThis, new); } @@ -2251,9 +2271,7 @@ rsRetVal MsgSetRcvFromIP(msg_t *pThis, prop_t *new) BEGINfunc prop.AddRef(new); - if(pThis->pRcvFromIP != NULL) - prop.Destruct(&pThis->pRcvFromIP); - pThis->pRcvFromIP = new; + MsgSetRcvFromIPWithoutAddRef(pThis, new); ENDfunc return RS_RET_OK; } diff --git a/runtime/net.c b/runtime/net.c index e5d8b4a4..b291213e 100644 --- a/runtime/net.c +++ b/runtime/net.c @@ -1117,91 +1117,15 @@ void debugListenInfo(int fd, char *type) } -/* Return a printable representation of a host address. - * Now (2007-07-16) also returns the full host name (if it could be obtained) - * in the second param [thanks to mildew@gmail.com for the patch]. - * The caller must provide buffer space for pszHost and pszHostFQDN. These - * buffers must be of size NI_MAXHOST. This is not checked here, because - * there is no way to check it. We use this way of doing things because it - * frees us from using dynamic memory allocation where it really does not - * pay. - * 2005-05-16 rgerhards: added IP representation. Must also be NI_MAXHOST +/* Return a printable representation of a host addresses. If + * a parameter is NULL, it is not set. rgerhards, 2013-01-22 */ -rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN, prop_t **ip) +rsRetVal +cvthname(struct sockaddr_storage *f, prop_t **localName, prop_t **fqdn, prop_t **ip) { DEFiRet; - prop_t *fqdnLowerCase; - register uchar *p; - int count; - int i; - assert(f != NULL); - assert(pszHost != NULL); - assert(pszHostFQDN != NULL); - - iRet = dnscacheLookup(f, NULL, &fqdnLowerCase, ip); - strcpy((char*)pszHostFQDN, (char*)propGetSzStr(fqdnLowerCase)); - prop.Destruct(&fqdnLowerCase); - - if(iRet == RS_RET_INVALID_SOURCE) { - strcpy((char*) pszHost, (char*) pszHostFQDN); /* we use whatever was provided as replacement */ - ABORT_FINALIZE(RS_RET_OK); /* this is handled, we are happy with it */ - } else if(iRet != RS_RET_OK) { - FINALIZE; /* we return whatever error state we have - can not handle it */ - } - - /* OK, the fqdn is now known. Now it is time to extract only the hostname - * part if we were instructed to do so. - */ - if(glbl.GetPreserveFQDN()) { - strcpy((char*)pszHost, (char*)pszHostFQDN); - } else { /* strip domain, if configured for this entry */ - p = (uchar*)strchr((char*)pszHostFQDN, '.'); /* find start of domain name "machine.example.com" */ - if(p == NULL) { /* do we have a domain part? */ - strcpy((char*)pszHost, (char*)pszHostFQDN); /* no! */ - } else { - i = p - pszHostFQDN; /* length of hostname */ - memcpy(pszHost, pszHostFQDN, i); - /* now check if we belong to any of the domain names that were specified - * in the -s command line option. If so, remove and we are done. - */ - if(glbl.GetStripDomains() != NULL) { - count=0; - while(glbl.GetStripDomains()[count]) { - if(strcmp((char*)(p + 1), glbl.GetStripDomains()[count]) == 0) { - pszHost[i] = '\0'; - FINALIZE; /* we are done */ - } - count++; - } - } - /* if we reach this point, we have not found any domain we should strip. Now - * we try and see if the host itself is listed in the -l command line option - * and so should be stripped also. If so, we do it and return. Please note that - * -l list FQDNs, not just the hostname part. If it did just list the hostname, the - * door would be wide-open for all kinds of mixing up of hosts. Because of this, - * you'll see comparison against the full string (pszHostFQDN) below. The termination - * still occurs at *p, which points at the first dot after the hostname. - * TODO: this must also go away - see comment above -- rgerhards, 2008-04-16 - */ - if(glbl.GetLocalHosts() != NULL) { - count=0; - while (glbl.GetLocalHosts()[count]) { - if (!strcmp((char*)pszHostFQDN, (char*)glbl.GetLocalHosts()[count])) { - pszHost[i] = '\0'; - FINALIZE; /* we are done */ - } - count++; - } - } - /* at this point, we have not found anything, so we need to copy - * over the rest. - */ - strcpy((char*)pszHost+i, (char*)p); - } - } - -finalize_it: + iRet = dnscacheLookup(f, NULL, fqdn, localName, ip); RETiRet; } diff --git a/runtime/net.h b/runtime/net.h index ec8ad5d8..b196116b 100644 --- a/runtime/net.h +++ b/runtime/net.h @@ -131,7 +131,7 @@ struct permittedPeers_s { /* interfaces */ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */ - rsRetVal (*cvthname)(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN, prop_t **ip); + rsRetVal (*cvthname)(struct sockaddr_storage *f, prop_t **localName, prop_t **fqdn, prop_t **ip); /* things to go away after proper modularization */ rsRetVal (*addAllowedSenderLine)(char* pName, uchar** ppRestOfConfLine); void (*PrintAllowedSenders)(int iListToPrint); diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c index ebfed722..f889a00e 100644 --- a/runtime/nsd_ptcp.c +++ b/runtime/nsd_ptcp.c @@ -258,7 +258,7 @@ FillRemHost(nsd_ptcp_t *pThis, struct sockaddr_storage *pAddr) ISOBJ_TYPE_assert(pThis, nsd_ptcp); assert(pAddr != NULL); - CHKiRet(dnscacheLookup(pAddr, &fqdn, NULL, &pThis->remoteIP)); + CHKiRet(dnscacheLookup(pAddr, &fqdn, NULL, NULL, &pThis->remoteIP)); /* We now have the names, so now let's allocate memory and store them permanently. * (side note: we may hold on to these values for quite a while, thus we trim their diff --git a/runtime/prop.c b/runtime/prop.c index a1f51ed1..cb89fac0 100644 --- a/runtime/prop.c +++ b/runtime/prop.c @@ -100,8 +100,7 @@ static int GetStringLen(prop_t *pThis) /* get string */ -rsRetVal -propGetString(prop_t *pThis, uchar **ppsz, int *plen) +rsRetVal GetString(prop_t *pThis, uchar **ppsz, int *plen) { BEGINfunc ISOBJ_TYPE_assert(pThis, prop); @@ -174,7 +173,7 @@ rsRetVal CreateOrReuseStringProp(prop_t **ppThis, uchar *psz, int len) CHKiRet(CreateStringProp(ppThis, psz, len)); } else { /* already exists, check if we can re-use it */ - propGetString(*ppThis, &pszPrev, &lenPrev); + GetString(*ppThis, &pszPrev, &lenPrev); if(len != lenPrev || ustrcmp(psz, pszPrev)) { /* different, need to discard old & create new one */ propDestruct(ppThis); @@ -213,7 +212,7 @@ CODESTARTobjQueryInterface(prop) pIf->Destruct = propDestruct; pIf->DebugPrint = propDebugPrint; pIf->SetString = SetString; - pIf->GetString = propGetString; + pIf->GetString = GetString; pIf->GetStringLen = GetStringLen; pIf->AddRef = AddRef; pIf->CreateStringProp = CreateStringProp; diff --git a/tools/syslogd.c b/tools/syslogd.c index e33c2f4b..ae1b3de5 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -500,9 +500,9 @@ finalize_it: */ static inline rsRetVal preprocessBatch(batch_t *pBatch) { - uchar fromHost[NI_MAXHOST]; - uchar fromHostFQDN[NI_MAXHOST]; prop_t *ip; + prop_t *fqdn; + prop_t *localName; prop_t *propFromHost = NULL; prop_t *propFromHostIP = NULL; int bSingleRuleset; @@ -520,17 +520,17 @@ preprocessBatch(batch_t *pBatch) { pMsg = pBatch->pElem[i].pMsg; if((pMsg->msgFlags & NEEDS_ACLCHK_U) != 0) { DBGPRINTF("msgConsumer: UDP ACL must be checked for message (hostname-based)\n"); - if(net.cvthname(pMsg->rcvFrom.pfrominet, fromHost, fromHostFQDN, &ip) != RS_RET_OK) + if(net.cvthname(pMsg->rcvFrom.pfrominet, &localName, &fqdn, &ip) != RS_RET_OK) continue; bIsPermitted = net.isAllowedSender2((uchar*)"UDP", - (struct sockaddr *)pMsg->rcvFrom.pfrominet, (char*)fromHostFQDN, 1); + (struct sockaddr *)pMsg->rcvFrom.pfrominet, (char*)propGetSzStr(fqdn), 1); if(!bIsPermitted) { DBGPRINTF("Message from '%s' discarded, not a permitted sender host\n", - fromHostFQDN); + propGetSzStr(fqdn)); pBatch->eltState[i] = BATCH_STATE_DISC; } else { /* save some of the info we obtained */ - MsgSetRcvFromStr(pMsg, fromHost, ustrlen(fromHost), &propFromHost); + MsgSetRcvFrom(pMsg, localName); CHKiRet(MsgSetRcvFromIP(pMsg, ip)); pMsg->msgFlags &= ~NEEDS_ACLCHK_U; } |