Exemplo n.º 1
0
/* open the kernel log - will be called inside the willRun() imklog
 * entry point. -- rgerhards, 2008-04-09
 */
rsRetVal
klogWillRunPrePrivDrop(modConfData_t *pModConf)
{
	char errmsg[2048];
	int r;
	DEFiRet;

	fklog = open((char*)GetPath(pModConf), O_RDONLY, 0);
	if (fklog < 0) {
		imklogLogIntMsg(LOG_ERR, "imklog: cannot open kernel log (%s): %s.",
			GetPath(pModConf), rs_strerror_r(errno, errmsg, sizeof(errmsg)));
		ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG);
	}

#	ifdef OS_LINUX
	/* Set level of kernel console messaging.. */
	if(pModConf->console_log_level != -1) {
		r = klogctl(8, NULL, pModConf->console_log_level);
		if(r != 0) {
			imklogLogIntMsg(LOG_WARNING, "imklog: cannot set console log level: %s",
				rs_strerror_r(errno, errmsg, sizeof(errmsg)));
			/* make sure we do not try to re-set! */
			pModConf->console_log_level = -1;
		}
	}
#	endif	/* #ifdef OS_LINUX */

finalize_it:
	RETiRet;
}
Exemplo n.º 2
0
/* write_pid
 *
 * Writes the pid to the specified file. If that fails 0 is
 * returned, otherwise the pid.
 */
int write_pid (char *pidfile)
{
  FILE *f;
  int fd;
  int pid;

  if ( ((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1)
       || ((f = fdopen(fd, "r+")) == NULL) ) {
      fprintf(stderr, "Can't open or create %s.\n", pidfile);
      return 0;
  }

 /* It seems to be acceptable that we do not lock the pid file
  * if we run under Solaris. In any case, it is highly unlikely
  * that two instances try to access this file. And flock is really
  * causing me grief on my initial steps on Solaris. Some time later,
  * we might re-enable it (or use some alternate method).
  * 2006-02-16 rgerhards
  */

#if HAVE_FLOCK
  if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
      fscanf(f, "%d", &pid);
      fclose(f);
      printf("Can't lock, lock is held by pid %d.\n", pid);
      return 0;
  }
#endif

  pid = getpid();
  if (!fprintf(f,"%d\n", pid)) {
      char errStr[1024];
      rs_strerror_r(errno, errStr, sizeof(errStr));
      printf("Can't write pid , %s.\n", errStr);
      close(fd);
      return 0;
  }
  fflush(f);

#if HAVE_FLOCK
  if (flock(fd, LOCK_UN) == -1) {
      char errStr[1024];
      rs_strerror_r(errno, errStr, sizeof(errStr));
      printf("Can't unlock pidfile %s, %s.\n", pidfile, errStr);
      close(fd);
      return 0;
  }
#endif
  close(fd);

  return pid;
}
Exemplo n.º 3
0
static int
should_use_so_bsdcompat(void)
{
#ifndef OS_BSD
    static int init_done = 0;
    static int so_bsdcompat_is_obsolete = 0;

    if (!init_done) {
	struct utsname myutsname;
	unsigned int version, patchlevel;

	init_done = 1;
	if (uname(&myutsname) < 0) {
		char errStr[1024];
		dbgprintf("uname: %s\r\n", rs_strerror_r(errno, errStr, sizeof(errStr)));
		return 1;
	}
	/* Format is <version>.<patchlevel>.<sublevel><extraversion>
	   where the first three are unsigned integers and the last
	   is an arbitrary string. We only care about the first two. */
	if (sscanf(myutsname.release, "%u.%u", &version, &patchlevel) != 2) {
	    dbgprintf("uname: unexpected release '%s'\r\n",
		    myutsname.release);
	    return 1;
	}
	/* SO_BSCOMPAT is deprecated and triggers warnings in 2.5
	   kernels. It is a no-op in 2.4 but not in 2.2 kernels. */
	if (version > 2 || (version == 2 && patchlevel >= 5))
	    so_bsdcompat_is_obsolete = 1;
    }
    return !so_bsdcompat_is_obsolete;
#else	/* #ifndef OS_BSD */
    return 1;
#endif	/* #ifndef OS_BSD */
}
Exemplo n.º 4
0
/* terminate a thread via the non-cancel interface
 * This is a separate function as it involves a bit more of code.
 * rgerhads, 2009-10-15
 */
static inline rsRetVal
thrdTerminateNonCancel(thrdInfo_t *pThis)
{
	struct timespec tTimeout;
	int ret;
	DEFiRet;
	assert(pThis != NULL);

	DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID);
	pThis->bShallStop = TRUE;
	do {
		d_pthread_mutex_lock(&pThis->mutThrd);
		pthread_kill(pThis->thrdID, SIGTTIN);
		timeoutComp(&tTimeout, 10); /* a fixed 10ms timeout, do after lock (may take long!) */
		ret = d_pthread_cond_timedwait(&pThis->condThrdTerm, &pThis->mutThrd, &tTimeout);
		d_pthread_mutex_unlock(&pThis->mutThrd);
		if(Debug) {
			if(ret == ETIMEDOUT) {
				dbgprintf("input thread term: had a timeout waiting on thread termination\n");
			} else if(ret == 0) {
				dbgprintf("input thread term: thread returned normally and is terminated\n");
			} else {
				char errStr[1024];
				int err = errno;
				rs_strerror_r(err, errStr, sizeof(errStr));
				dbgprintf("input thread term: cond_wait returned with error %d: %s\n",
					  err, errStr);
			}
		}
	} while(pThis->bIsActive);
	DBGPRINTF("non-cancel input thread termination succeeded for thread 0x%x\n", (unsigned) pThis->thrdID);

	RETiRet;
}
Exemplo n.º 5
0
/* Read kernel log while data are available, split into lines.
 */
static void
readklog(modConfData_t *pModConf)
{
	char *p, *q;
	int len, i;
	int iMaxLine;
	uchar bufRcv[128*1024+1];
	char errmsg[2048];
	uchar *pRcv = NULL; /* receive buffer */

	iMaxLine = klog_getMaxLine();

	/* we optimize performance: if iMaxLine is below our fixed size buffer (which
	 * usually is sufficiently large), we use this buffer. if it is higher, heap memory
	 * is used. We could use alloca() to achive a similar aspect, but there are so
	 * many issues with alloca() that I do not want to take that route.
	 * rgerhards, 2008-09-02
	 */
	if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
		pRcv = bufRcv;
	} else {
		if((pRcv = (uchar*) MALLOC(sizeof(uchar) * (iMaxLine + 1))) == NULL)
			iMaxLine = sizeof(bufRcv) - 1; /* better this than noting */
	}

	len = 0;
	for (;;) {
		dbgprintf("imklog(BSD/Linux) waiting for kernel log line\n");
		i = read(fklog, pRcv + len, iMaxLine - len);
		if (i > 0) {
			pRcv[i + len] = '\0';
		} else {
			if (i < 0 && errno != EINTR && errno != EAGAIN) {
				imklogLogIntMsg(LOG_ERR,
				       "imklog: error reading kernel log - shutting down: %s",
					rs_strerror_r(errno, errmsg, sizeof(errmsg)));
				fklog = -1;
			}
			break;
		}

		for (p = (char*)pRcv; (q = strchr(p, '\n')) != NULL; p = q + 1) {
			*q = '\0';
			submitSyslog(pModConf, LOG_INFO, (uchar*) p);
		}
		len = strlen(p);
		if (len >= iMaxLine - 1) {
			submitSyslog(pModConf, LOG_INFO, (uchar*)p);
			len = 0;
		}
		if(len > 0)
			memmove(pRcv, p, len + 1);
	}
	if (len > 0)
		submitSyslog(pModConf, LOG_INFO, pRcv);

	if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1)
		free(pRcv);
}
Exemplo n.º 6
0
/* do the physical open() call on a file.
 */
static rsRetVal
doPhysOpen(strm_t *pThis)
{
	int iFlags = 0;
	DEFiRet;
	ISOBJ_TYPE_assert(pThis, strm);

	/* compute which flags we need to provide to open */
	switch(pThis->tOperationsMode) {
		case STREAMMODE_READ:
			iFlags = O_CLOEXEC | O_NOCTTY | O_RDONLY;
			break;
		case STREAMMODE_WRITE:	/* legacy mode used inside queue engine */
			iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT;
			break;
		case STREAMMODE_WRITE_TRUNC:
			iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT | O_TRUNC;
			break;
		case STREAMMODE_WRITE_APPEND:
			iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT | O_APPEND;
			break;
		default:assert(0);
			break;
	}
	if(pThis->sType == STREAMTYPE_NAMED_PIPE) {
		DBGPRINTF("Note: stream '%s' is a named pipe, open with O_NONBLOCK\n", pThis->pszCurrFName);
		iFlags |= O_NONBLOCK;
	}

	pThis->fd = open((char*)pThis->pszCurrFName, iFlags, pThis->tOpenMode);
	DBGPRINTF("file '%s' opened as #%d with mode %d\n", pThis->pszCurrFName, pThis->fd, pThis->tOpenMode);
	if(pThis->fd == -1) {
		char errStr[1024];
		int err = errno;
		rs_strerror_r(err, errStr, sizeof(errStr));
		DBGOPRINT((obj_t*) pThis, "open error %d, file '%s': %s\n", errno, pThis->pszCurrFName, errStr);
		if(err == ENOENT)
			ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
		else
			ABORT_FINALIZE(RS_RET_IO_ERROR);
	} else {
		if(!ustrcmp(pThis->pszCurrFName, UCHAR_CONSTANT(_PATH_CONSOLE)) || isatty(pThis->fd)) {
			DBGPRINTF("file %d is a tty-type file\n", pThis->fd);
			pThis->bIsTTY = 1;
		} else {
			pThis->bIsTTY = 0;
		}
	}

finalize_it:
	RETiRet;
}
Exemplo n.º 7
0
/* terminate a thread via the non-cancel interface
 * This is a separate function as it involves a bit more of code.
 * rgerhads, 2009-10-15
 */
static inline rsRetVal
thrdTerminateNonCancel(thrdInfo_t *pThis)
{
	struct timespec tTimeout;
	int ret;
	int was_active;
	DEFiRet;
	assert(pThis != NULL);

	DBGPRINTF("request term via SIGTTIN for input thread '%s' 0x%x\n",
		  pThis->name, (unsigned) pThis->thrdID);

	pThis->bShallStop = RSTRUE;
	timeoutComp(&tTimeout, 1000); /* a fixed 1sec timeout */
	d_pthread_mutex_lock(&pThis->mutThrd);
	was_active = pThis->bIsActive;
	while(was_active) {
		pthread_kill(pThis->thrdID, SIGTTIN);
		ret = d_pthread_cond_timedwait(&pThis->condThrdTerm, &pThis->mutThrd, &tTimeout);
		if(ret == ETIMEDOUT) {
			DBGPRINTF("input thread term: timeout expired waiting on thread %s termination - canceling\n",
				pThis->name);
			pthread_cancel(pThis->thrdID);
			break;
		} else if(ret != 0) {
			char errStr[1024];
			int err = errno;
			rs_strerror_r(err, errStr, sizeof(errStr));
			DBGPRINTF("input thread term: cond_wait returned with error %d: %s\n",
				  err, errStr);
		}
		was_active = pThis->bIsActive;
	}
	d_pthread_mutex_unlock(&pThis->mutThrd);

	if(was_active) {
		DBGPRINTF("non-cancel input thread termination FAILED for thread %s 0x%x\n",
			  pThis->name, (unsigned) pThis->thrdID);
	} else {
		DBGPRINTF("non-cancel input thread termination succeeded for thread %s 0x%x\n",
			  pThis->name, (unsigned) pThis->thrdID);
	}

	RETiRet;
}
Exemplo n.º 8
0
/* This function receives data from a socket indicated to be ready
 * to receive and submits the message received for processing.
 * rgerhards, 2007-12-20
 * Interface changed so that this function is passed the array index
 * of the socket which is to be processed. This eases access to the
 * growing number of properties. -- rgerhards, 2008-08-01
 */
static rsRetVal
readLog(int fd, uchar *pRcv, int iMaxLine)
{
	DEFiRet;
	struct strbuf data;
	struct strbuf ctl;
	struct log_ctl hdr;
	int flags;
	msg_t *pMsg;
	int ret;
	char errStr[1024];

	data.buf = (char*)pRcv;
	data.maxlen = iMaxLine;
	ctl.maxlen = sizeof (struct log_ctl);
	ctl.buf = (caddr_t)&hdr;
	flags = 0;
	ret = getmsg(fd, &ctl, &data, &flags);
	if(ret < 0) {
		if(errno == EINTR) {
			FINALIZE;
		} else 	{
			int en = errno;
			rs_strerror_r(errno, errStr, sizeof(errStr));
			DBGPRINTF("imsolaris: stream input error on fd %d: %s.\n", fd, errStr);
			errmsg.LogError(en, NO_ERRCODE, "imsolaris: stream input error: %s", errStr);
			tryRecover();
		}	
	} else {
		DBGPRINTF("imsolaris: message from log stream %d: %s\n", fd, pRcv);
		pRcv[data.len] = '\0'; /* make sure it is a valid C-String */
		CHKiRet(msgConstruct(&pMsg));
		MsgSetInputName(pMsg, pInputName);
		MsgSetRawMsg(pMsg, (char*)pRcv, strlen((char*)pRcv));
		MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
		pMsg->iFacility = LOG_FAC(hdr.pri);
		pMsg->iSeverity = LOG_PRI(hdr.pri);
		pMsg->msgFlags = NEEDS_PARSING | NO_PRI_IN_RAW;
		CHKiRet(submitMsg(pMsg));
	}

finalize_it:
	RETiRet;
}
Exemplo n.º 9
0
/* The following function is responsible for initializing a
 * MySQL connection.
 * Initially added 2004-10-28 mmeckelein
 */
static rsRetVal initMySQL(wrkrInstanceData_t *pWrkrData, int bSilent)
{
	instanceData *pData;
	DEFiRet;

	ASSERT(pWrkrData->hmysql == NULL);
	pData = pWrkrData->pData;
	pWrkrData->hmysql = mysql_init(NULL);
	if(pWrkrData->hmysql == NULL) {
		errmsg.LogError(0, RS_RET_SUSPENDED, "can not initialize MySQL handle");
		iRet = RS_RET_SUSPENDED;
	} else { /* we could get the handle, now on with work... */
		mysql_options(pWrkrData->hmysql,MYSQL_READ_DEFAULT_GROUP,((pData->configsection!=NULL)?(char*)pData->configsection:"client"));
		if(pData->configfile!=NULL){
			FILE * fp;
			fp=fopen((char*)pData->configfile,"r");
			int err=errno;
			if(fp==NULL){
				char msg[512];
				snprintf(msg,sizeof(msg),"Could not open '%s' for reading",pData->configfile);
				if(bSilent) {
					char errStr[512];
					rs_strerror_r(err, errStr, sizeof(errStr));
					dbgprintf("mysql configuration error(%d): %s - %s\n",err,msg,errStr);
				} else
					errmsg.LogError(err,NO_ERRCODE,"mysql configuration error: %s\n",msg);
			} else {
				fclose(fp);
				mysql_options(pWrkrData->hmysql,MYSQL_READ_DEFAULT_FILE,pData->configfile);
			}
		}
		/* Connect to database */
		if(mysql_real_connect(pWrkrData->hmysql, pData->dbsrv, pData->dbuid,
				      pData->dbpwd, pData->dbname, pData->dbsrvPort, NULL, 0) == NULL) {
			reportDBError(pWrkrData, bSilent);
			closeMySQL(pWrkrData); /* ignore any error we may get */
			ABORT_FINALIZE(RS_RET_SUSPENDED);
		}
		mysql_autocommit(pWrkrData->hmysql, 0);
	}

finalize_it:
	RETiRet;
}
Exemplo n.º 10
0
/* make sure the kernel log is readable after dropping privileges
 */
rsRetVal
klogWillRunPostPrivDrop(modConfData_t *pModConf)
{
	char errmsg[2048];
	int r;
	DEFiRet;

	/* this normally returns EINVAL */
	/* on an OpenVZ VM, we get EPERM */
	r = read(fklog, NULL, 0);
	if (r < 0 && errno != EINVAL) {
		imklogLogIntMsg(LOG_ERR, "imklog: cannot open kernel log (%s): %s.",
			GetPath(pModConf), rs_strerror_r(errno, errmsg, sizeof(errmsg)));
		fklog = -1;
		ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG);
	}

finalize_it:
	RETiRet;
}
Exemplo n.º 11
0
/* once the system is fully initialized, we wait for new messages.
 * We may think about replacing this with a read-loop, thus saving
 * us the overhead of the poll.
 * The timeout variable is the timeout to use for poll. During startup,
 * it should be set to 0 (non-blocking) and later to -1 (infinit, blocking).
 * This mimics the (strange) behaviour of the original syslogd.
 * rgerhards, 2010-04-19
 */
static inline rsRetVal
getMsgs(thrdInfo_t *pThrd, int timeout)
{
	DEFiRet;
	int nfds;
	int iMaxLine;
	uchar *pRcv = NULL; /* receive buffer */
	uchar bufRcv[4096+1];
	char errStr[1024];

	iMaxLine = glbl.GetMaxLine();

	/* we optimize performance: if iMaxLine is below 4K (which it is in almost all
	 * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory
	 * is used. We could use alloca() to achive a similar aspect, but there are so
	 * many issues with alloca() that I do not want to take that route.
	 * rgerhards, 2008-09-02
	 */
	if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
		pRcv = bufRcv;
	} else {
		CHKmalloc(pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1)));
	}

	 while(pThrd->bShallStop != TRUE) {
		DBGPRINTF("imsolaris: waiting for next message (timeout %d)...\n", timeout);
		if(timeout == 0) {
			nfds = poll(&sun_Pfd, 1, timeout); /* wait without timeout */

			if(pThrd->bShallStop == TRUE) {
				break;
			}

			if(nfds == 0) {
				if(timeout == 0) {
					DBGPRINTF("imsolaris: no more messages, getMsgs() terminates\n");
					FINALIZE;
				} else {
					continue;
				}	
			}		

			if(nfds < 0) {
				if(errno != EINTR) {
					int en = errno;
					rs_strerror_r(en, errStr, sizeof(errStr));
					DBGPRINTF("imsolaris: poll error: %d = %s.\n", errno, errStr);
					errmsg.LogError(en, NO_ERRCODE, "imsolaris: poll error: %s",
							errStr);
				}
				continue;
			}
			if(sun_Pfd.revents & POLLIN) {
				readLog(sun_Pfd.fd, pRcv, iMaxLine);
			} else if(sun_Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
				tryRecover();
			}
		} else {
			/* if we have an infinite wait, we do not use poll at all
			 * I'd consider this a waste of time. However, I do not totally
			 * remove the code, as it may be useful if we decide at some
			 * point to provide a capability to support multiple input streams
			 * at once (this may be useful for a jail). In that case, the poll()
			 * loop would be needed, and so it doesn't make much sense to change
			 * the code to not support it. -- rgerhards, 2010-04-20
			 */
			readLog(sun_Pfd.fd, pRcv, iMaxLine);
		}

	}

finalize_it:
	if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1)
		free(pRcv);

	RETiRet;
}
Exemplo n.º 12
0
/* note: widely-deployed json_c 0.9 does NOT support incremental
 * parsing. In order to keep compatible with e.g. Ubuntu 12.04LTS,
 * we read the file into one big memory buffer and parse it at once.
 * While this is not very elegant, it will not pose any real issue
 * for "reasonable" lookup tables (and "unreasonably" large ones
 * will probably have other issues as well...).
 */
static rsRetVal
lookupReadFile(lookup_t *pThis)
{
	struct json_tokener *tokener = NULL;
	struct json_object *json = NULL;
	int eno;
	char errStr[1024];
	char *iobuf = NULL;
	int fd;
	ssize_t nread;
	struct stat sb;
	DEFiRet;


	if(stat((char*)pThis->filename, &sb) == -1) {
		eno = errno;
		errmsg.LogError(0, RS_RET_FILE_NOT_FOUND,
			"lookup table file '%s' stat failed: %s",
			pThis->filename, rs_strerror_r(eno, errStr, sizeof(errStr)));
		ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
	}

	CHKmalloc(iobuf = malloc(sb.st_size));

	if((fd = open((const char*) pThis->filename, O_RDONLY)) == -1) {
		eno = errno;
		errmsg.LogError(0, RS_RET_FILE_NOT_FOUND,
			"lookup table file '%s' could not be opened: %s",
			pThis->filename, rs_strerror_r(eno, errStr, sizeof(errStr)));
		ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
	}

	tokener = json_tokener_new();
	nread = read(fd, iobuf, sb.st_size);
	if(nread != (ssize_t) sb.st_size) {
		eno = errno;
		errmsg.LogError(0, RS_RET_READ_ERR,
			"lookup table file '%s' read error: %s",
			pThis->filename, rs_strerror_r(eno, errStr, sizeof(errStr)));
		ABORT_FINALIZE(RS_RET_READ_ERR);
	}

	json = json_tokener_parse_ex(tokener, iobuf, sb.st_size);
	if(json == NULL) {
		errmsg.LogError(0, RS_RET_JSON_PARSE_ERR,
			"lookup table file '%s' json parsing error",
			pThis->filename);
		ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR);
	}
	free(iobuf); /* early free to sever resources*/
	iobuf = NULL; /* make sure no double-free */

	/* got json object, now populate our own in-memory structure */
	CHKiRet(lookupBuildTable(pThis, json));

finalize_it:
	free(iobuf);
	if(tokener != NULL)
		json_tokener_free(tokener);
	if(json != NULL)
		json_object_put(json);
	RETiRet;
}
Exemplo n.º 13
0
/* creates the UDP listen sockets
 * 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
 */
static int *
create_udp_socket(uchar *hostname, uchar *pszPort, int bIsServer, int rcvbuf, int ipfreebind)
{
        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));
	if(bIsServer)
		hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
	else
		hints.ai_flags = AI_NUMERICSERV;
        hints.ai_family = glbl.GetDefPFFamily();
        hints.ai_socktype = SOCK_DGRAM;
        error = getaddrinfo((char*) hostname, (char*) pszPort, &hints, &res);
        if(error) {
               errmsg.LogError(0, NO_ERRCODE, "%s",  gai_strerror(error));
	       errmsg.LogError(0, NO_ERRCODE, "UDP message reception disabled due to error logged in last message.\n");
	       return NULL;
	}

        /* Count max number of sockets we may open */
        for (maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
		/* EMPTY */;
        socks = MALLOC((maxs+1) * sizeof(int));
        if (socks == NULL) {
               errmsg.LogError(0, NO_ERRCODE, "couldn't allocate memory for UDP sockets, suspending UDP message reception");
               freeaddrinfo(res);
               return NULL;
        }

        *socks = 0;   /* num of sockets counter at start of array */
        s = socks + 1;
	for (r = res; r != NULL ; r = r->ai_next) {
               *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
        	if (*s < 0) {
			if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT))
				errmsg.LogError(errno, NO_ERRCODE, "create_udp_socket(), socket");
				/* it is debateble if PF_INET with EAFNOSUPPORT should
				 * also be ignored...
				 */
                        continue;
                }

#		ifdef IPV6_V6ONLY
                if (r->ai_family == AF_INET6) {
                	int ion = 1;
			if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
			      (char *)&ion, sizeof (ion)) < 0) {
			errmsg.LogError(errno, NO_ERRCODE, "setsockopt");
			close(*s);
			*s = -1;
			continue;
                	}
                }
#		endif

		/* if we have an error, we "just" suspend that socket. Eventually
		 * other sockets will work. At the end of this function, we check
		 * if we managed to open at least one socket. If not, we'll write
		 * a "inet suspended" message and declare failure. Else we use
		 * what we could obtain.
		 * rgerhards, 2007-06-22
		 */
       		if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
			       (char *) &on, sizeof(on)) < 0 ) {
			errmsg.LogError(errno, NO_ERRCODE, "setsockopt(REUSEADDR)");
                        close(*s);
			*s = -1;
			continue;
		}

		/* We need to enable BSD compatibility. Otherwise an attacker
		 * could flood our log files by sending us tons of ICMP errors.
		 */
#if !defined(OS_BSD) && !defined(__hpux)
		if (should_use_so_bsdcompat()) {
			if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT,
					(char *) &on, sizeof(on)) < 0) {
				errmsg.LogError(errno, NO_ERRCODE, "setsockopt(BSDCOMPAT)");
                                close(*s);
				*s = -1;
				continue;
			}
		}
#endif
		/* We must not block on the network socket, in case a packet
		 * gets lost between select and recv, otherwise the process
		 * will stall until the timeout, and other processes trying to
		 * log will also stall.
		 * Patch vom Colin Phipps <*****@*****.**> to the original
		 * sysklogd source. Applied to rsyslogd on 2005-10-19.
		 */
		if ((sockflags = fcntl(*s, F_GETFL)) != -1) {
			sockflags |= O_NONBLOCK;
			/* SETFL could fail too, so get it caught by the subsequent
			 * error check.
			 */
			sockflags = fcntl(*s, F_SETFL, sockflags);
		}
		if (sockflags == -1) {
			errmsg.LogError(errno, NO_ERRCODE, "fcntl(O_NONBLOCK)");
                        close(*s);
			*s = -1;
			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 os socket rcvbuf size %d\n", *s, actrcvbuf);
				if(rcvbuf != 0 && actrcvbuf/2 != rcvbuf) {
					errmsg.LogError(errno, NO_ERRCODE,
						"cannot set os socket rcvbuf size %d for socket %d, value now is %d",
						rcvbuf, *s, actrcvbuf/2);
				}
			} else {
				dbgprintf("could not obtain os socket 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
			 * systems the IPv6 socket does also accept IPv4 sockets. So an IPv4
			 * socket can not listen on the same port as an IPv6 socket. The only
			 * workaround is to ignore the "socket in use" error. This is what we
			 * do if we have to.
			 */
			if(     (bind(*s, r->ai_addr, r->ai_addrlen) < 0)
	#		ifndef IPV6_V6ONLY
			     && (errno != EADDRINUSE)
	#		endif
			   ) {
				if (errno == EADDRNOTAVAIL && ipfreebind != IPFREEBIND_DISABLED) {
					if (setsockopt(*s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on)) < 0) {
						errmsg.LogError(errno, NO_ERRCODE, "setsockopt(IP_FREEBIND)");
					}
					else if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
						errmsg.LogError(errno, NO_ERRCODE, "bind with IP_FREEBIND");
					} else {
						if (ipfreebind >= IPFREEBIND_ENABLED_WITH_LOG)
							errmsg.LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "bound address %s IP free", hostname);
						continue;
					}
				}
				close(*s);
				*s = -1;
				continue;
			}
		}

                (*socks)++;
                s++;
	}

        if(res != NULL)
               freeaddrinfo(res);

	if(Debug && *socks != maxs)
		dbgprintf("We could initialize %d UDP listen sockets out of %d we received "
		 	"- this may or may not be an error indication.\n", *socks, maxs);

        if(*socks == 0) {
		errmsg.LogError(0, NO_ERRCODE, "No UDP listen socket could successfully be initialized, "
			 "message reception via UDP disabled.\n");
		/* we do NOT need to free any sockets, because there were none... */
        	free(socks);
		return(NULL);
	}

	return(socks);
}