From 38aa077ccb3bac7493c401dbd91b97037d208d54 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 11 Jul 2013 10:01:57 +0200 Subject: imudp: add ability to specify SO_RCVBUF size (rcvbufSize parameter) --- ChangeLog | 1 + doc/imudp.html | 37 ++++++++++++++++++++++++++----------- plugins/imudp/imudp.c | 7 ++++++- plugins/omudpspoof/omudpspoof.c | 2 +- runtime/net.c | 35 ++++++++++++++++++++++++++++++++++- runtime/net.h | 2 +- tools/omfwd.c | 2 +- 7 files changed, 70 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index a0e50d02..10ee1019 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ +- imudp: add ability to specify SO_RCVBUF size (rcvbufSize parameter) - impstats: add process resource usage counters [via getrusage()] ---------------------------------------------------------------------------- Version 7.2.7 [v7-stable] 2013-04-17 diff --git a/doc/imudp.html b/doc/imudp.html index 105e0b2a..961bbeba 100644 --- a/doc/imudp.html +++ b/doc/imudp.html @@ -18,8 +18,8 @@ multiple input actions.

-

Configuration Directives:

-

Global Directives:

+

Configuration Parameters:

+

Module Parameters:

-

Action Directives:

+

Action Parameters:

Caveats/Known Bugs: -Caveats/Known Bugs: - -

Sample:

+

Legacy Sample:

This sets up an UPD server on port 514:

-

[rsyslog.conf overview] @@ -96,7 +111,7 @@ $UDPServerRun 514

This documentation is part of the rsyslog project.
-Copyright © 2009 by Rainer +Copyright © 2009-2013 by Rainer Gerhards and Adiscon. Released under the GNU GPL version 3 or higher.

diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index 06e1471d..ec128d14 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -109,6 +109,7 @@ struct instanceConf_s { uchar *pszBindPort; /* Port to bind socket to */ uchar *pszBindRuleset; /* name of ruleset to bind to */ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ + int rcvbuf; /* 0 means: do not set, keep OS default */ struct instanceConf_s *next; }; @@ -140,6 +141,7 @@ static struct cnfparamblk modpblk = static struct cnfparamdescr inppdescr[] = { { "port", eCmdHdlrArray, CNFPARAM_REQUIRED }, /* legacy: InputTCPServerRun */ { "address", eCmdHdlrString, 0 }, + { "rcvbufsize", eCmdHdlrSize, 0 }, { "ruleset", eCmdHdlrString, 0 } }; static struct cnfparamblk inppblk = @@ -165,6 +167,7 @@ createInstance(instanceConf_t **pinst) inst->pszBindPort = NULL; inst->pszBindAddr = NULL; inst->pszBindRuleset = NULL; + inst->rcvbuf = 0; /* node created, let's add to config */ if(loadModConf->tail == NULL) { @@ -239,7 +242,7 @@ addListner(instanceConf_t *inst) DBGPRINTF("Trying to open syslog UDP ports at %s:%s.\n", bindName, inst->pszBindPort); - newSocks = net.create_udp_socket(bindAddr, port, 1); + newSocks = net.create_udp_socket(bindAddr, port, 1, inst->rcvbuf); if(newSocks != NULL) { /* we now need to add the new sockets to the existing set */ /* ready to copy */ @@ -682,6 +685,8 @@ createListner(es_str_t *port, struct cnfparamvals *pvals) inst->pszBindAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "ruleset")) { inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "rcvbufsize")) { + inst->rcvbuf = (int) pvals[i].val.d.n; } else { dbgprintf("imudp: program error, non-handled " "param '%s'\n", inppblk.descr[i].name); diff --git a/plugins/omudpspoof/omudpspoof.c b/plugins/omudpspoof/omudpspoof.c index a45d49fa..69144426 100644 --- a/plugins/omudpspoof/omudpspoof.c +++ b/plugins/omudpspoof/omudpspoof.c @@ -441,7 +441,7 @@ static rsRetVal doTryResume(instanceData *pData) } DBGPRINTF("%s found, resuming.\n", pData->host); pData->f_addr = res; - pData->pSockArray = net.create_udp_socket((uchar*)pData->host, NULL, 0); + pData->pSockArray = net.create_udp_socket((uchar*)pData->host, NULL, 0, 0); finalize_it: if(iRet != RS_RET_OK) { diff --git a/runtime/net.c b/runtime/net.c index 1a8f2438..8f5ad3d2 100644 --- a/runtime/net.c +++ b/runtime/net.c @@ -1269,12 +1269,16 @@ void closeUDPListenSockets(int *pSockArr) * hostname and/or pszPort may be NULL, but not both! * bIsServer indicates if a server socket should be created * 1 - server, 0 - client + * param rcvbuf indicates desired rcvbuf size; 0 means OS default */ -int *create_udp_socket(uchar *hostname, uchar *pszPort, int bIsServer) +int *create_udp_socket(uchar *hostname, uchar *pszPort, int bIsServer, int rcvbuf) { struct addrinfo hints, *res, *r; int error, maxs, *s, *socks, on = 1; int sockflags; + int actrcvbuf; + socklen_t optlen; + char errStr[1024]; assert(!((pszPort == NULL) && (hostname == NULL))); memset(&hints, 0, sizeof(hints)); @@ -1377,6 +1381,35 @@ int *create_udp_socket(uchar *hostname, uchar *pszPort, int bIsServer) continue; } + if(rcvbuf != 0) { +# if defined(SO_RCVBUFFORCE) + if(setsockopt(*s, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf, sizeof(rcvbuf)) < 0) +# endif + { + /* if we fail, try to do it the regular way. Experiments show that at + * least some platforms do not return an error here, but silently set + * it to the max permitted value. So we do our error check a bit + * differently by querying the size below. + */ + setsockopt(*s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); + } + } + + if(Debug || rcvbuf != 0) { + optlen = sizeof(actrcvbuf); + if(getsockopt(*s, SOL_SOCKET, SO_RCVBUF, &actrcvbuf, &optlen) == 0) { + dbgprintf("socket %d, actual rcvbuf size %d\n", *s, actrcvbuf); + if(rcvbuf != 0 && actrcvbuf/2 != rcvbuf) { + errmsg.LogError(errno, NO_ERRCODE, + "cannot set rcvbuf size %d for socket %d, value now is %d", + rcvbuf, *s, actrcvbuf/2); + } + } else { + dbgprintf("could not obtain rcvbuf size for socket %d: %s\n", + *s, rs_strerror_r(errno, errStr, sizeof(errStr))); + } + } + if(bIsServer) { /* rgerhards, 2007-06-22: if we run on a kernel that does not support * the IPV6_V6ONLY socket option, we need to use a work-around. On such diff --git a/runtime/net.h b/runtime/net.h index 1b41c81c..36f9eb41 100644 --- a/runtime/net.h +++ b/runtime/net.h @@ -137,7 +137,7 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */ void (*PrintAllowedSenders)(int iListToPrint); void (*clearAllowedSenders)(uchar*); void (*debugListenInfo)(int fd, char *type); - int *(*create_udp_socket)(uchar *hostname, uchar *LogPort, int bIsServer); + int *(*create_udp_socket)(uchar *hostname, uchar *LogPort, int bIsServer, int rcvbuf); void (*closeUDPListenSockets)(int *finet); int (*isAllowedSender)(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost); /* deprecated! */ rsRetVal (*getLocalHostname)(uchar**); diff --git a/tools/omfwd.c b/tools/omfwd.c index 129392d2..a7f8bf7b 100644 --- a/tools/omfwd.c +++ b/tools/omfwd.c @@ -576,7 +576,7 @@ static rsRetVal doTryResume(instanceData *pData) pData->f_addr = res; pData->bIsConnected = 1; if(pData->pSockArray == NULL) { - pData->pSockArray = net.create_udp_socket((uchar*)pData->target, NULL, 0); + pData->pSockArray = net.create_udp_socket((uchar*)pData->target, NULL, 0, 0); } } else { CHKiRet(TCPSendInit((void*)pData)); -- cgit v1.2.3