import rsyslog-8.1911.0-2.el8
This commit is contained in:
parent
52bfb17394
commit
3f7674c145
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
SOURCES/rsyslog-8.37.0.tar.gz
|
||||
SOURCES/rsyslog-doc-8.37.0.tar.gz
|
||||
SOURCES/rsyslog-8.1911.0.tar.gz
|
||||
SOURCES/rsyslog-doc-8.1911.0.tar.gz
|
||||
|
@ -1,2 +1,2 @@
|
||||
43076e3010fc3fd5178201a916beb93848b5249c SOURCES/rsyslog-8.37.0.tar.gz
|
||||
4c75f56e2d55c4c87d07781fb6d9deabf63395fb SOURCES/rsyslog-doc-8.37.0.tar.gz
|
||||
30dfc2b99d73598788e2bd0d0ac45e16e7c3a3d5 SOURCES/rsyslog-8.1911.0.tar.gz
|
||||
8bcb23571ab8011b712ccf52acee20f8940b7f03 SOURCES/rsyslog-doc-8.1911.0.tar.gz
|
||||
|
@ -2,19 +2,19 @@ diff -up ./plugins/imjournal/imjournal.c.default-tag ./plugins/imjournal/imjourn
|
||||
--- ./plugins/imjournal/imjournal.c.default-tag 2018-05-17 08:50:11.416418022 -0400
|
||||
+++ ./plugins/imjournal/imjournal.c 2018-05-17 08:53:02.884418022 -0400
|
||||
@@ -78,6 +78,7 @@ static struct configSettings_s {
|
||||
int bUseJnlPID;
|
||||
char *usePid;
|
||||
int bWorkAroundJournalBug;
|
||||
int bWorkAroundJournalBug; /* deprecated, left for backwards compatibility only */
|
||||
int bFsync;
|
||||
int bRemote;
|
||||
+ char *dfltTag;
|
||||
} cs;
|
||||
|
||||
static rsRetVal facilityHdlr(uchar **pp, void *pVal);
|
||||
@@ -93,7 +94,8 @@ static struct cnfparamdescr modpdescr[]
|
||||
{ "defaultfacility", eCmdHdlrString, 0 },
|
||||
{ "usepidfromsystem", eCmdHdlrBinary, 0 },
|
||||
{ "usepid", eCmdHdlrString, 0 },
|
||||
- { "workaroundjournalbug", eCmdHdlrBinary, 0 }
|
||||
+ { "workaroundjournalbug", eCmdHdlrBinary, 0 },
|
||||
{ "workaroundjournalbug", eCmdHdlrBinary, 0 },
|
||||
{ "fsync", eCmdHdlrBinary, 0 },
|
||||
- { "remote", eCmdHdlrBinary, 0 }
|
||||
+ { "remote", eCmdHdlrBinary, 0 },
|
||||
+ { "defaulttag", eCmdHdlrGetWord, 0 }
|
||||
};
|
||||
static struct cnfparamblk modpblk =
|
||||
@ -34,10 +34,10 @@ diff -up ./plugins/imjournal/imjournal.c.default-tag ./plugins/imjournal/imjourn
|
||||
- char *sys_iden;
|
||||
+ char *sys_iden = NULL;
|
||||
char *sys_iden_help = NULL;
|
||||
char *c = NULL;
|
||||
|
||||
const void *get;
|
||||
@@ -331,7 +334,7 @@ readjournal(void)
|
||||
if (sd_journal_get_data(j, "SYSLOG_IDENTIFIER", &get, &length) >= 0) {
|
||||
if (journalGetData("SYSLOG_IDENTIFIER", &get, &length) >= 0) {
|
||||
CHKiRet(sanitizeValue(((const char *)get) + 18, length - 18, &sys_iden));
|
||||
} else {
|
||||
- CHKmalloc(sys_iden = strdup("journal"));
|
||||
@ -58,9 +58,9 @@ diff -up ./plugins/imjournal/imjournal.c.default-tag ./plugins/imjournal/imjourn
|
||||
pidFieldName = "_PID";
|
||||
bPidFallBack = 0;
|
||||
@@ -732,6 +740,7 @@ CODESTARTbeginCnfLoad
|
||||
cs.bUseJnlPID = -1;
|
||||
cs.usePid = NULL;
|
||||
cs.bWorkAroundJournalBug = 0;
|
||||
cs.bWorkAroundJournalBug = 1;
|
||||
cs.bFsync = 0;
|
||||
cs.bRemote = 0;
|
||||
+ cs.dfltTag = NULL;
|
||||
ENDbeginCnfLoad
|
||||
|
||||
@ -70,13 +70,13 @@ diff -up ./plugins/imjournal/imjournal.c.default-tag ./plugins/imjournal/imjourn
|
||||
free(cs.stateFile);
|
||||
free(cs.usePid);
|
||||
+ free(cs.dfltTag);
|
||||
statsobj.Destruct(&(statsCounter.stats));
|
||||
free(journalContext.cursor);
|
||||
statsobj.Destruct(&(statsCounter.stats));
|
||||
ENDfreeCnf
|
||||
|
||||
@@ -832,6 +842,8 @@ CODESTARTsetModCnf
|
||||
cs.usePid = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
} else if (!strcmp(modpblk.descr[i].name, "workaroundjournalbug")) {
|
||||
cs.bWorkAroundJournalBug = (int) pvals[i].val.d.n;
|
||||
cs.bFsync = (int) pvals[i].val.d.n;
|
||||
} else if (!strcmp(modpblk.descr[i].name, "remote")) {
|
||||
cs.bRemote = (int) pvals[i].val.d.n;
|
||||
+ } else if (!strcmp(modpblk.descr[i].name, "defaulttag")) {
|
||||
+ cs.dfltTag = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
} else {
|
142
SOURCES/rsyslog-8.1911.0-rhbz1763757-imfile-statefiles.patch
Normal file
142
SOURCES/rsyslog-8.1911.0-rhbz1763757-imfile-statefiles.patch
Normal file
@ -0,0 +1,142 @@
|
||||
From ac30968b7858d4ca3743d2b4d296eca543864fe2 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Vymazal <jvymazal@redhat.com>
|
||||
Date: Fri, 22 Nov 2019 14:25:59 +0100
|
||||
Subject: [PATCH] Thorougher state-file renaming and cleaning
|
||||
|
||||
Now checking if file-id changes and reanming - cleaning state file
|
||||
accordingly and always checking and cleaning old inode-only style
|
||||
state files.
|
||||
---
|
||||
plugins/imfile/imfile.c | 66 +++++++++++++++++++++++++++--------------
|
||||
1 file changed, 43 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
|
||||
index d9bf0fbb6d..9db2b47ac9 100644
|
||||
--- a/plugins/imfile/imfile.c
|
||||
+++ b/plugins/imfile/imfile.c
|
||||
@@ -182,6 +182,7 @@ struct act_obj_s {
|
||||
time_t timeoutBase; /* what time to calculate the timeout against? */
|
||||
/* file dynamic data */
|
||||
char file_id[FILE_ID_HASH_SIZE]; /* file id for this entry, once we could obtain it */
|
||||
+ char file_id_prev[FILE_ID_HASH_SIZE]; /* previous file id for this entry, set if changed */
|
||||
int in_move; /* workaround for inotify move: if set, state file must not be deleted */
|
||||
ino_t ino; /* current inode nbr */
|
||||
int fd; /* fd to file in order to obtain file_id (needs to be preserved across move) */
|
||||
@@ -711,7 +712,7 @@ act_obj_add(fs_edge_t *const edge, const char *const name, const int is_file,
|
||||
if (is_file) {
|
||||
LogError(errno, RS_RET_ERR, "imfile: error accessing file '%s'", name);
|
||||
} else { /* reporting only in debug for dirs as higher lvl paths are likely blocked by selinux */
|
||||
- DBGPRINTF("imfile: error accessing file '%s'", name);
|
||||
+ DBGPRINTF("imfile: error accessing directory '%s'", name);
|
||||
}
|
||||
FINALIZE;
|
||||
}
|
||||
@@ -727,6 +728,7 @@ act_obj_add(fs_edge_t *const edge, const char *const name, const int is_file,
|
||||
act->ino = ino;
|
||||
act->fd = fd;
|
||||
act->file_id[0] = '\0';
|
||||
+ act->file_id_prev[0] = '\0';
|
||||
act->is_symlink = is_symlink;
|
||||
if (source) { /* we are target of symlink */
|
||||
CHKmalloc(act->source_name = strdup(source));
|
||||
@@ -1256,17 +1258,15 @@ get_file_id_hash(const char *data, size_t lendata,
|
||||
static void ATTR_NONNULL(1)
|
||||
getFileID(act_obj_t *const act)
|
||||
{
|
||||
- if(act->file_id[0] != '\0') {
|
||||
- return; /* everything already done */
|
||||
- }
|
||||
+ /* save the old id for cleaning purposes */
|
||||
+ strncpy(act->file_id_prev, (const char*)act->file_id, FILE_ID_HASH_SIZE);
|
||||
+ act->file_id[0] = '\0';
|
||||
assert(act->fd >= 0); /* fd must have been opened at act_obj_t creation! */
|
||||
char filedata[FILE_ID_SIZE];
|
||||
+ lseek(act->fd, 0, SEEK_SET); /* Seek to beginning of file so we have correct id */
|
||||
const int r = read(act->fd, filedata, FILE_ID_SIZE);
|
||||
if(r == FILE_ID_SIZE) {
|
||||
get_file_id_hash(filedata, sizeof(filedata), act->file_id, sizeof(act->file_id));
|
||||
- dbgprintf("file_id '%s' obtained, closing monitoring file handle\n", act->file_id);
|
||||
- close(act->fd); /* we will never go here! */
|
||||
- act->fd = -1;
|
||||
} else {
|
||||
DBGPRINTF("getFileID partial or error read, ret %d\n", r);
|
||||
}
|
||||
@@ -1378,28 +1378,13 @@ openFileWithStateFile(act_obj_t *const act)
|
||||
if(fd < 0) {
|
||||
if(errno == ENOENT) {
|
||||
if(act->file_id[0] != '\0') {
|
||||
- const char *pszSFNamHash = strdup((const char*)pszSFNam);
|
||||
- CHKmalloc(pszSFNamHash);
|
||||
DBGPRINTF("state file %s for %s does not exist - trying to see if "
|
||||
"inode-only file exists\n", pszSFNam, act->name);
|
||||
getFullStateFileName(statefn, "", pszSFNam, sizeof(pszSFNam));
|
||||
fd = open((char*)pszSFNam, O_CLOEXEC | O_NOCTTY | O_RDONLY, 0600);
|
||||
if(fd >= 0) {
|
||||
- dbgprintf("found inode-only state file, renaming it now that we "
|
||||
- "know the file_id, new name: %s\n", pszSFNamHash);
|
||||
- /* we now can use identify the file, so let's rename it */
|
||||
- if(rename((const char*)pszSFNam, pszSFNamHash) != 0) {
|
||||
- LogError(errno, RS_RET_IO_ERROR,
|
||||
- "imfile error trying to rename state file for '%s' - "
|
||||
- "ignoring this error, usually this means a file no "
|
||||
- "longer file is left over, but this may also cause "
|
||||
- "some real trouble. Still the best we can do ",
|
||||
- act->name);
|
||||
- free((void*) pszSFNamHash);
|
||||
- ABORT_FINALIZE(RS_RET_IO_ERROR);
|
||||
- }
|
||||
+ dbgprintf("found inode-only state file, will be renamed at next persist\n");
|
||||
}
|
||||
- free((void*) pszSFNamHash);
|
||||
}
|
||||
if(fd < 0) {
|
||||
DBGPRINTF("state file %s for %s does not exist - trying to see if "
|
||||
@@ -2609,6 +2594,36 @@ atomicWriteStateFile(const char *fn, const char *content)
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
+/* This function should be called after any file ID change - that is if
|
||||
+ * file grown from hash-only statefile, or was truncated, this will ensure
|
||||
+ * we delete the old file so we do not make garbage in our working dir and
|
||||
+ * there are no leftover statefiles which can in theory later bind to something
|
||||
+ * and cause data loss.
|
||||
+ * jvymazal 2019-11-27
|
||||
+ */
|
||||
+static void
|
||||
+removeOldStatefile(const uchar *statefn, const char *hashToDelete)
|
||||
+{
|
||||
+ int ret;
|
||||
+ uchar statefname[MAXFNAME];
|
||||
+
|
||||
+ getFullStateFileName(statefn, hashToDelete, statefname, sizeof(statefname));
|
||||
+ DBGPRINTF("removing old state file: '%s'\n", statefname);
|
||||
+ ret = unlink((const char*)statefname);
|
||||
+ if(ret != 0) {
|
||||
+ if (errno != ENOENT) {
|
||||
+ LogError(errno, RS_RET_IO_ERROR,
|
||||
+ "imfile error trying to delete old state file: '%s' - ignoring this "
|
||||
+ "error, usually this means a file no longer file is left over, but "
|
||||
+ "this may also cause some real trouble. Still the best we can do ",
|
||||
+ statefname);
|
||||
+ } else {
|
||||
+ DBGPRINTF("trying to delete no longer valid statefile '%s' which no "
|
||||
+ "longer exists (probably already deleted)\n", statefname);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
|
||||
/* This function persists information for a specific file being monitored.
|
||||
* To do so, it simply persists the stream object. We do NOT abort on error
|
||||
@@ -2660,6 +2675,11 @@ persistStrmState(act_obj_t *const act)
|
||||
CHKiRet(atomicWriteStateFile((const char*)statefname, jstr));
|
||||
json_object_put(json);
|
||||
|
||||
+ /* file-id changed remove the old statefile */
|
||||
+ if (strncmp((const char *)act->file_id_prev, (const char *)act->file_id, FILE_ID_HASH_SIZE)) {
|
||||
+ removeOldStatefile(statefn, act->file_id_prev);
|
||||
+ }
|
||||
+
|
||||
finalize_it:
|
||||
if(iRet != RS_RET_OK) {
|
||||
LogError(0, iRet, "imfile: could not persist state "
|
@ -8,7 +8,7 @@ diff -up ./rsyslog.service.in.service ./rsyslog.service.in
|
||||
+Wants=network.target network-online.target
|
||||
+After=network.target network-online.target
|
||||
Documentation=man:rsyslogd(8)
|
||||
Documentation=http://www.rsyslog.com/doc/
|
||||
Documentation=https://www.rsyslog.com/doc/
|
||||
|
||||
[Service]
|
||||
Type=notify
|
@ -1,416 +0,0 @@
|
||||
From 3822da837e4d531e8a9cd78ae76359a410f8d98d Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Vymazal <jvymazal@redhat.com>
|
||||
Date: Thu, 31 May 2018 16:30:08 +0200
|
||||
Subject: [PATCH] Symlink support for imfile
|
||||
|
||||
this introduces symlink detection and following as well
|
||||
as monitoring changes on them. Also added test for the new
|
||||
functionality and ensuring the original symlink behavior
|
||||
stays as well.
|
||||
---
|
||||
plugins/imfile/imfile.c | 182 +++++++++++++++++++++++++++----------
|
||||
1 file changed, 133 insertions(+), 49 deletions(-)
|
||||
|
||||
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
|
||||
index 3c9308bfe..4ca23d2ca 100644
|
||||
--- a/plugins/imfile/imfile.c
|
||||
+++ b/plugins/imfile/imfile.c
|
||||
@@ -152,6 +152,7 @@ struct act_obj_s {
|
||||
fs_edge_t *edge; /* edge which this object belongs to */
|
||||
char *name; /* full path name of active object */
|
||||
char *basename; /* only basename */ //TODO: remove when refactoring rename support
|
||||
+ char *source_name; /* if this object is target of a symlink, source_name is its name (else NULL) */
|
||||
//char *statefile; /* base name of state file (for move operations) */
|
||||
int wd;
|
||||
#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
|
||||
@@ -167,6 +168,7 @@ struct act_obj_s {
|
||||
int nRecords; /**< How many records did we process before persisting the stream? */
|
||||
ratelimit_t *ratelimiter;
|
||||
multi_submit_t multiSub;
|
||||
+ int is_symlink;
|
||||
};
|
||||
struct fs_edge_s {
|
||||
fs_node_t *parent;
|
||||
@@ -181,7 +182,8 @@ struct act_obj_s {
|
||||
instanceConf_t **instarr;
|
||||
};
|
||||
struct fs_node_s {
|
||||
- fs_edge_t *edges;
|
||||
+ fs_edge_t *edges; /* NULL in leaf nodes */
|
||||
+ fs_node_t *root; /* node one level up (NULL for file system root) */
|
||||
};
|
||||
|
||||
|
||||
@@ -189,7 +191,7 @@ static rsRetVal persistStrmState(act_obj_t *);
|
||||
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
|
||||
static rsRetVal ATTR_NONNULL(1) pollFile(act_obj_t *act);
|
||||
static int ATTR_NONNULL() getBasename(uchar *const __restrict__ basen, uchar *const __restrict__ path);
|
||||
-static void ATTR_NONNULL() act_obj_unlink(act_obj_t *const act);
|
||||
+static void ATTR_NONNULL() act_obj_unlink(act_obj_t *act);
|
||||
static uchar * ATTR_NONNULL(1, 2) getStateFileName(const act_obj_t *, uchar *, const size_t);
|
||||
static int ATTR_NONNULL() getFullStateFileName(const uchar *const, uchar *const pszout, const size_t ilenout);
|
||||
|
||||
@@ -483,14 +485,17 @@ in_setupWatch(act_obj_t *const act, const int is_file)
|
||||
goto done;
|
||||
|
||||
wd = inotify_add_watch(ino_fd, act->name,
|
||||
- (is_file) ? IN_MODIFY : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
|
||||
+ (is_file) ? IN_MODIFY|IN_DONT_FOLLOW : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
|
||||
if(wd < 0) {
|
||||
- LogError(errno, RS_RET_IO_ERROR, "imfile: cannot watch object '%s'",
|
||||
- act->name);
|
||||
+ if (errno == EACCES) { /* There is high probability of selinux denial on top-level paths */
|
||||
+ DBGPRINTF("imfile: permission denied when adding watch for '%s'\n", act->name);
|
||||
+ } else {
|
||||
+ LogError(errno, RS_RET_IO_ERROR, "imfile: cannot watch object '%s'", act->name);
|
||||
+ }
|
||||
goto done;
|
||||
}
|
||||
wdmapAdd(wd, act);
|
||||
- DBGPRINTF("in_setupDirWatch: watch %d added for dir %s(%p)\n", wd, act->name, act);
|
||||
+ DBGPRINTF("in_setupWatch: watch %d added for %s(object %p)\n", wd, act->name, act);
|
||||
done: return wd;
|
||||
}
|
||||
|
||||
@@ -605,7 +610,7 @@ done: return;
|
||||
static void ATTR_NONNULL()
|
||||
fen_setupWatch(act_obj_t *const act __attribute__((unused)))
|
||||
{
|
||||
- DBGPRINTF("fen_setupWatch: DUMMY CALLED - not on Solaris?");
|
||||
+ DBGPRINTF("fen_setupWatch: DUMMY CALLED - not on Solaris?\n");
|
||||
}
|
||||
#endif /* FEN */
|
||||
|
||||
@@ -633,38 +638,48 @@ fs_node_print(const fs_node_t *const node, const int level)
|
||||
}
|
||||
}
|
||||
|
||||
-
|
||||
/* add a new file system object if it not yet exists, ignore call
|
||||
* if it already does.
|
||||
*/
|
||||
-static rsRetVal ATTR_NONNULL()
|
||||
+static rsRetVal ATTR_NONNULL(1,2)
|
||||
act_obj_add(fs_edge_t *const edge, const char *const name, const int is_file,
|
||||
- const ino_t ino)
|
||||
+ const ino_t ino, const int is_symlink, const char *const source)
|
||||
{
|
||||
act_obj_t *act;
|
||||
char basename[MAXFNAME];
|
||||
DEFiRet;
|
||||
|
||||
- DBGPRINTF("act_obj_add: edge %p, name '%s'\n", edge, name);
|
||||
+ DBGPRINTF("act_obj_add: edge %p, name '%s' (source '%s')\n", edge, name, source? source : "---");
|
||||
for(act = edge->active ; act != NULL ; act = act->next) {
|
||||
if(!strcmp(act->name, name)) {
|
||||
- DBGPRINTF("active object '%s' already exists in '%s' - no need to add\n",
|
||||
- name, edge->path);
|
||||
- FINALIZE;
|
||||
+ if (!source || !act->source_name || !strcmp(act->source_name, source)) {
|
||||
+ DBGPRINTF("active object '%s' already exists in '%s' - no need to add\n",
|
||||
+ name, edge->path);
|
||||
+ FINALIZE;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
DBGPRINTF("add new active object '%s' in '%s'\n", name, edge->path);
|
||||
CHKmalloc(act = calloc(sizeof(act_obj_t), 1));
|
||||
CHKmalloc(act->name = strdup(name));
|
||||
- getBasename((uchar*)basename, (uchar*)name);
|
||||
- CHKmalloc(act->basename = strdup(basename));
|
||||
+ if (-1 == getBasename((uchar*)basename, (uchar*)name)) {
|
||||
+ CHKmalloc(act->basename = strdup(name)); /* assume basename is same as name */
|
||||
+ } else {
|
||||
+ CHKmalloc(act->basename = strdup(basename));
|
||||
+ }
|
||||
act->edge = edge;
|
||||
act->ino = ino;
|
||||
+ act->is_symlink = is_symlink;
|
||||
+ if (source) { /* we are target of symlink */
|
||||
+ CHKmalloc(act->source_name = strdup(source));
|
||||
+ } else {
|
||||
+ act->source_name = NULL;
|
||||
+ }
|
||||
#ifdef HAVE_INOTIFY_INIT
|
||||
act->wd = in_setupWatch(act, is_file);
|
||||
#endif
|
||||
fen_setupWatch(act);
|
||||
- if(is_file) {
|
||||
+ if(is_file && !is_symlink) {
|
||||
const instanceConf_t *const inst = edge->instarr[0];// TODO: same file, multiple instances?
|
||||
CHKiRet(ratelimitNew(&act->ratelimiter, "imfile", name));
|
||||
CHKmalloc(act->multiSub.ppMsgs = MALLOC(inst->nMultiSub * sizeof(smsg_t *)));
|
||||
@@ -702,27 +717,24 @@ detect_updates(fs_edge_t *const edge)
|
||||
{
|
||||
act_obj_t *act;
|
||||
struct stat fileInfo;
|
||||
+ int restart = 0;
|
||||
|
||||
- for(act = edge->active ; act != NULL ; ) {
|
||||
+ for(act = edge->active ; act != NULL ; act = act->next) {
|
||||
DBGPRINTF("detect_updates checking active obj '%s'\n", act->name);
|
||||
- const int r = stat(act->name, &fileInfo);
|
||||
+ const int r = lstat(act->name, &fileInfo);
|
||||
if(r == -1) { /* object gone away? */
|
||||
DBGPRINTF("object gone away, unlinking: '%s'\n", act->name);
|
||||
- act_obj_t *toDel = act;
|
||||
- act = act->next;
|
||||
- DBGPRINTF("new next act %p\n", act);
|
||||
- act_obj_unlink(toDel);
|
||||
- continue;
|
||||
+ act_obj_unlink(act);
|
||||
+ restart = 1;
|
||||
+ break;
|
||||
}
|
||||
// TODO: add inode check for change notification!
|
||||
|
||||
- /* Note: active nodes may get deleted, so we need to do the
|
||||
- * pointer advancement at the end of the for loop!
|
||||
- */
|
||||
- act = act->next;
|
||||
}
|
||||
|
||||
-
|
||||
+ if (restart) {
|
||||
+ detect_updates(edge);
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -746,14 +758,52 @@ poll_active_files(fs_edge_t *const edge)
|
||||
}
|
||||
}
|
||||
|
||||
+static rsRetVal ATTR_NONNULL()
|
||||
+process_symlink(fs_edge_t *const chld, const char *symlink)
|
||||
+{
|
||||
+ DEFiRet;
|
||||
+ char *target = NULL;
|
||||
+ CHKmalloc(target = realpath(symlink, target));
|
||||
+ struct stat fileInfo;
|
||||
+ if(lstat(target, &fileInfo) != 0) {
|
||||
+ LogError(errno, RS_RET_ERR, "imfile: process_symlink: cannot stat file '%s' - ignored", target);
|
||||
+ FINALIZE;
|
||||
+ }
|
||||
+ const int is_file = (S_ISREG(fileInfo.st_mode));
|
||||
+ DBGPRINTF("process_symlink: found '%s', File: %d (config file: %d), symlink: %d\n",
|
||||
+ target, is_file, chld->is_file, 0);
|
||||
+ if (act_obj_add(chld, target, is_file, fileInfo.st_ino, 0, symlink) == RS_RET_OK) {
|
||||
+ /* need to watch parent target as well for proper rotation support */
|
||||
+ uint idx = ustrlen(chld->active->name) - ustrlen(chld->active->basename);
|
||||
+ if (idx) { /* basename is different from name */
|
||||
+ char parent[MAXFNAME];
|
||||
+ idx--; /* move past trailing slash */
|
||||
+ memcpy(parent, chld->active->name, idx);
|
||||
+ parent[idx] = '\0';
|
||||
+ if(lstat(parent, &fileInfo) != 0) {
|
||||
+ LogError(errno, RS_RET_ERR,
|
||||
+ "imfile: process_symlink: cannot stat directory '%s' - ignored", parent);
|
||||
+ FINALIZE;
|
||||
+ }
|
||||
+ if (chld->parent->root->edges) {
|
||||
+ DBGPRINTF("process_symlink: adding parent '%s' of target '%s'\n", parent, target);
|
||||
+ act_obj_add(chld->parent->root->edges, parent, 0, fileInfo.st_ino, 0, NULL);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+finalize_it:
|
||||
+ free(target);
|
||||
+ RETiRet;
|
||||
+}
|
||||
|
||||
-static void ATTR_NONNULL() poll_tree(fs_edge_t *const chld);
|
||||
static void ATTR_NONNULL()
|
||||
poll_tree(fs_edge_t *const chld)
|
||||
{
|
||||
struct stat fileInfo;
|
||||
glob_t files;
|
||||
int need_globfree = 0;
|
||||
+ int issymlink;
|
||||
DBGPRINTF("poll_tree: chld %p, name '%s', path: %s\n", chld, chld->name, chld->path);
|
||||
detect_updates(chld);
|
||||
const int ret = glob((char*)chld->path, runModConf->sortFiles|GLOB_BRACE, NULL, &files);
|
||||
@@ -766,18 +803,27 @@ poll_tree(fs_edge_t *const chld)
|
||||
goto done;
|
||||
}
|
||||
char *const file = files.gl_pathv[i];
|
||||
- if(stat(file, &fileInfo) != 0) {
|
||||
+ if(lstat(file, &fileInfo) != 0) {
|
||||
LogError(errno, RS_RET_ERR,
|
||||
"imfile: poll_tree cannot stat file '%s' - ignored", file);
|
||||
continue;
|
||||
}
|
||||
|
||||
- const int is_file = S_ISREG(fileInfo.st_mode);
|
||||
- DBGPRINTF("poll_tree: found '%s', File: %d (config file: %d)\n",
|
||||
- file, is_file, chld->is_file);
|
||||
+ if (S_ISLNK(fileInfo.st_mode)) {
|
||||
+ rsRetVal slink_ret = process_symlink(chld, file);
|
||||
+ if (slink_ret != RS_RET_OK) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ issymlink = 1;
|
||||
+ } else {
|
||||
+ issymlink = 0;
|
||||
+ }
|
||||
+ const int is_file = (S_ISREG(fileInfo.st_mode) || issymlink);
|
||||
+ DBGPRINTF("poll_tree: found '%s', File: %d (config file: %d), symlink: %d\n",
|
||||
+ file, is_file, chld->is_file, issymlink);
|
||||
if(!is_file && S_ISREG(fileInfo.st_mode)) {
|
||||
LogMsg(0, RS_RET_ERR, LOG_WARNING,
|
||||
- "imfile: '%s' is neither a regular file nor a "
|
||||
+ "imfile: '%s' is neither a regular file, symlink, nor a "
|
||||
"directory - ignored", file);
|
||||
continue;
|
||||
}
|
||||
@@ -788,7 +834,7 @@ poll_tree(fs_edge_t *const chld)
|
||||
(chld->is_file) ? "FILE" : "DIRECTORY");
|
||||
continue;
|
||||
}
|
||||
- act_obj_add(chld, file, is_file, fileInfo.st_ino);
|
||||
+ act_obj_add(chld, file, is_file, fileInfo.st_ino, issymlink, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,8 +875,20 @@ act_obj_destroy(act_obj_t *const act, const int is_deleted)
|
||||
if(act == NULL)
|
||||
return;
|
||||
|
||||
- DBGPRINTF("act_obj_destroy: act %p '%s', wd %d, pStrm %p, is_deleted %d, in_move %d\n",
|
||||
- act, act->name, act->wd, act->pStrm, is_deleted, act->in_move);
|
||||
+ DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n",
|
||||
+ act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted,
|
||||
+ act->in_move);
|
||||
+ if(act->is_symlink && is_deleted) {
|
||||
+ act_obj_t *target_act;
|
||||
+ for(target_act = act->edge->active ; target_act != NULL ; target_act = target_act->next) {
|
||||
+ if(target_act->source_name && !strcmp(target_act->source_name, act->name)) {
|
||||
+ DBGPRINTF("act_obj_destroy: unlinking slink target %s of %s "
|
||||
+ "symlink\n", target_act->name, act->name);
|
||||
+ act_obj_unlink(target_act);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
if(act->ratelimiter != NULL) {
|
||||
ratelimitDestruct(act->ratelimiter);
|
||||
}
|
||||
@@ -862,6 +920,7 @@ act_obj_destroy(act_obj_t *const act, const int is_deleted)
|
||||
}
|
||||
#endif
|
||||
free(act->basename);
|
||||
+ free(act->source_name);
|
||||
//free(act->statefile);
|
||||
free(act->multiSub.ppMsgs);
|
||||
#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
|
||||
@@ -909,7 +968,7 @@ chk_active(const act_obj_t *act, const act_obj_t *const deleted)
|
||||
* destruct it.
|
||||
*/
|
||||
static void //ATTR_NONNULL()
|
||||
-act_obj_unlink(act_obj_t *const act)
|
||||
+act_obj_unlink(act_obj_t *act)
|
||||
{
|
||||
DBGPRINTF("act_obj_unlink %p: %s\n", act, act->name);
|
||||
if(act->prev == NULL) {
|
||||
@@ -921,6 +980,7 @@ act_obj_unlink(act_obj_t *const act)
|
||||
act->next->prev = act->prev;
|
||||
}
|
||||
act_obj_destroy(act, 1);
|
||||
+ act = NULL;
|
||||
//dbgprintf("printout of fs tree post unlink\n");
|
||||
//fs_node_print(runModConf->conf_tree, 0);
|
||||
//dbg_wdmapPrint("wdmap after");
|
||||
@@ -1025,6 +1038,7 @@ fs_node_walk(fs_node_t *const node,
|
||||
*/
|
||||
static rsRetVal
|
||||
fs_node_add(fs_node_t *const node,
|
||||
+ fs_node_t *const source,
|
||||
const uchar *const toFind,
|
||||
const size_t pathIdx,
|
||||
instanceConf_t *const inst)
|
||||
@@ -1053,6 +1067,7 @@ fs_node_add(fs_node_t *const node,
|
||||
memcpy(name, toFind+pathIdx, len);
|
||||
name[len] = '\0';
|
||||
DBGPRINTF("fs_node_add: name '%s'\n", name);
|
||||
+ node->root = source;
|
||||
|
||||
fs_edge_t *chld;
|
||||
for(chld = node->edges ; chld != NULL ; chld = chld->next) {
|
||||
@@ -1064,7 +1079,7 @@ fs_node_add(fs_node_t *const node,
|
||||
chld->instarr[chld->ninst-1] = inst;
|
||||
/* recurse */
|
||||
if(!isFile) {
|
||||
- CHKiRet(fs_node_add(chld->node, toFind, nextPathIdx, inst));
|
||||
+ CHKiRet(fs_node_add(chld->node, node, toFind, nextPathIdx, inst));
|
||||
}
|
||||
FINALIZE;
|
||||
}
|
||||
@@ -1086,7 +1101,7 @@ fs_node_add(fs_node_t *const node,
|
||||
DBGPRINTF("fs_node_add(%p, '%s') returns %p\n", node, toFind, newchld->node);
|
||||
|
||||
if(!isFile) {
|
||||
- CHKiRet(fs_node_add(newchld->node, toFind, nextPathIdx, inst));
|
||||
+ CHKiRet(fs_node_add(newchld->node, node, toFind, nextPathIdx, inst));
|
||||
}
|
||||
|
||||
/* link to list */
|
||||
@@ -1162,7 +1222,11 @@ enqLine(act_obj_t *const act,
|
||||
msgSetPRI(pMsg, inst->iFacility | inst->iSeverity);
|
||||
MsgSetRuleset(pMsg, inst->pBindRuleset);
|
||||
if(inst->addMetadata) {
|
||||
- metadata_values[0] = (const uchar*)act->name;
|
||||
+ if (act->source_name) {
|
||||
+ metadata_values[0] = (const uchar*)act->source_name;
|
||||
+ } else {
|
||||
+ metadata_values[0] = (const uchar*)act->name;
|
||||
+ }
|
||||
snprintf((char *)file_offset, MAX_OFFSET_REPRESENTATION_NUM_BYTES+1, "%lld", strtOffs);
|
||||
metadata_values[1] = file_offset;
|
||||
msgAddMultiMetadata(pMsg, metadata_names, metadata_values, 2);
|
||||
@@ -1389,13 +1453,16 @@ pollFile(act_obj_t *const act)
|
||||
{
|
||||
cstr_t *pCStr = NULL;
|
||||
DEFiRet;
|
||||
+ if (act->is_symlink) {
|
||||
+ FINALIZE; /* no reason to poll symlink file */
|
||||
+ }
|
||||
/* Note: we must do pthread_cleanup_push() immediately, because the POSIX macros
|
||||
* otherwise do not work if I include the _cleanup_pop() inside an if... -- rgerhards, 2008-08-14
|
||||
*/
|
||||
pthread_cleanup_push(pollFileCancelCleanup, &pCStr);
|
||||
iRet = pollFileReal(act, &pCStr);
|
||||
pthread_cleanup_pop(0);
|
||||
- RETiRet;
|
||||
+finalize_it: RETiRet;
|
||||
}
|
||||
|
||||
|
||||
@@ -1931,7 +1946,7 @@ CODESTARTactivateCnf
|
||||
"be processed. Reason", inst->pszFileName);
|
||||
}
|
||||
}
|
||||
- fs_node_add(runModConf->conf_tree, inst->pszFileName, 0, inst);
|
||||
+ fs_node_add(runModConf->conf_tree, NULL, inst->pszFileName, 0, inst);
|
||||
}
|
||||
|
||||
if(Debug) {
|
||||
@@ -2031,6 +2113,9 @@ flag_in_move(fs_edge_t *const edge, const char *name_moved)
|
||||
DBGPRINTF("name check fails, '%s' != '%s'\n", act->basename, name_moved);
|
||||
}
|
||||
}
|
||||
+ if (!act && edge->next) {
|
||||
+ flag_in_move(edge->next, name_moved);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void ATTR_NONNULL(1)
|
||||
@@ -2057,7 +2145,7 @@ in_processEvent(struct inotify_event *ev)
|
||||
}
|
||||
if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO)) {
|
||||
fs_node_walk(etry->act->edge->node, poll_tree);
|
||||
- } else if(etry->act->edge->is_file) {
|
||||
+ } else if(etry->act->edge->is_file && !(etry->act->is_symlink)) {
|
||||
in_handleFileEvent(ev, etry); // esentially poll_file()!
|
||||
} else {
|
||||
fs_node_walk(etry->act->edge->node, poll_tree);
|
@ -1,286 +0,0 @@
|
||||
From 9ac54f0d7d70b8a9879889b4522a1d552fca1100 Mon Sep 17 00:00:00 2001
|
||||
From: Noriko Hosoi <nhosoi@momo7.localdomain>
|
||||
Date: Thu, 12 Jul 2018 11:52:04 -0700
|
||||
Subject: [PATCH] Introducing an option preservecase to imudp and imtcp module
|
||||
for managing the case of FROMHOST value.
|
||||
|
||||
Usage:
|
||||
module(load="imudp" [preservecase="on"|"off"])
|
||||
module(load="imtdp" [preservecase="on"|"off"])
|
||||
|
||||
If preservecase="on", FROMHOST value is handled in the case sensitive manner.
|
||||
If preservecase="off", FROMHOST value is handled in the case insensitive manner.
|
||||
|
||||
To maintain the current behaviour, the default value of preservecase is
|
||||
"on" for imtcp and "off" for imudp.
|
||||
|
||||
Incremented tcpsrvCURR_IF_VERSION by 1.
|
||||
|
||||
References:
|
||||
https://github.com/rsyslog/rsyslog/pull/2774
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1309698
|
||||
---
|
||||
plugins/imtcp/imtcp.c | 14 ++++++++++++--
|
||||
plugins/imudp/imudp.c | 15 ++++++++++++---
|
||||
runtime/msg.c | 6 +++++-
|
||||
runtime/msg.h | 2 ++
|
||||
runtime/net.c | 2 +-
|
||||
runtime/tcpsrv.c | 21 +++++++++++++++++++++
|
||||
runtime/tcpsrv.h | 5 ++++-
|
||||
7 files changed, 57 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c
|
||||
index 8e3dcc0a2..45fa240b5 100644
|
||||
--- a/plugins/imtcp/imtcp.c
|
||||
+++ b/plugins/imtcp/imtcp.c
|
||||
@@ -100,6 +100,7 @@ static struct configSettings_s {
|
||||
int bDisableLFDelim;
|
||||
int discardTruncatedMsg;
|
||||
int bUseFlowControl;
|
||||
+ int bPreserveCase;
|
||||
uchar *gnutlsPriorityString;
|
||||
uchar *pszStrmDrvrAuthMode;
|
||||
uchar *pszInputName;
|
||||
@@ -144,6 +145,7 @@ struct modConfData_s {
|
||||
uchar *pszStrmDrvrAuthMode; /* authentication mode to use */
|
||||
struct cnfarray *permittedPeers;
|
||||
sbool configSetViaV2Method;
|
||||
+ sbool bPreserveCase; /* preserve case of fromhost; true by default */
|
||||
};
|
||||
|
||||
static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
|
||||
@@ -169,7 +171,8 @@ static struct cnfparamdescr modpdescr[] = {
|
||||
{ "keepalive.probes", eCmdHdlrPositiveInt, 0 },
|
||||
{ "keepalive.time", eCmdHdlrPositiveInt, 0 },
|
||||
{ "keepalive.interval", eCmdHdlrPositiveInt, 0 },
|
||||
- { "gnutlsprioritystring", eCmdHdlrString, 0 }
|
||||
+ { "gnutlsprioritystring", eCmdHdlrString, 0 },
|
||||
+ { "preservecase", eCmdHdlrBinary, 0 }
|
||||
};
|
||||
static struct cnfparamblk modpblk =
|
||||
{ CNFPARAMBLK_VERSION,
|
||||
@@ -375,6 +378,7 @@ addListner(modConfData_t *modConf, instanceConf_t *inst)
|
||||
if(pPermPeersRoot != NULL) {
|
||||
CHKiRet(tcpsrv.SetDrvrPermPeers(pOurTcpsrv, pPermPeersRoot));
|
||||
}
|
||||
+ CHKiRet(tcpsrv.SetPreserveCase(pOurTcpsrv, modConf->bPreserveCase));
|
||||
}
|
||||
|
||||
/* initialized, now add socket and listener params */
|
||||
@@ -473,6 +477,7 @@ CODESTARTbeginCnfLoad
|
||||
loadModConf->pszStrmDrvrAuthMode = NULL;
|
||||
loadModConf->permittedPeers = NULL;
|
||||
loadModConf->configSetViaV2Method = 0;
|
||||
+ loadModConf->bPreserveCase = 1; /* default to true */
|
||||
bLegacyCnfModGlobalsPermitted = 1;
|
||||
/* init legacy config variables */
|
||||
cs.pszStrmDrvrAuthMode = NULL;
|
||||
@@ -543,6 +548,8 @@ CODESTARTsetModCnf
|
||||
loadModConf->pszStrmDrvrName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
} else if(!strcmp(modpblk.descr[i].name, "permittedpeer")) {
|
||||
loadModConf->permittedPeers = cnfarrayDup(pvals[i].val.d.ar);
|
||||
+ } else if(!strcmp(modpblk.descr[i].name, "preservecase")) {
|
||||
+ loadModConf->bPreserveCase = (int) pvals[i].val.d.n;
|
||||
} else {
|
||||
dbgprintf("imtcp: program error, non-handled "
|
||||
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
|
||||
@@ -584,6 +591,7 @@ CODESTARTendCnfLoad
|
||||
loadModConf->pszStrmDrvrAuthMode = cs.pszStrmDrvrAuthMode;
|
||||
cs.pszStrmDrvrAuthMode = NULL;
|
||||
}
|
||||
+ pModConf->bPreserveCase = cs.bPreserveCase;
|
||||
}
|
||||
free(cs.pszStrmDrvrAuthMode);
|
||||
cs.pszStrmDrvrAuthMode = NULL;
|
||||
@@ -731,6 +739,7 @@ resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unus
|
||||
cs.pszInputName = NULL;
|
||||
free(cs.pszStrmDrvrAuthMode);
|
||||
cs.pszStrmDrvrAuthMode = NULL;
|
||||
+ cs.bPreserveCase = 1;
|
||||
return RS_RET_OK;
|
||||
}
|
||||
|
||||
@@ -797,7 +806,8 @@ CODEmodInit_QueryRegCFSLineHdlr
|
||||
NULL, &cs.bEmitMsgOnClose, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
|
||||
CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverstreamdrivermode"), 0, eCmdHdlrInt,
|
||||
NULL, &cs.iStrmDrvrMode, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
|
||||
-
|
||||
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverpreservecase"), 1, eCmdHdlrBinary,
|
||||
+ NULL, &cs.bPreserveCase, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
|
||||
CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("resetconfigvariables"), 1, eCmdHdlrCustomHandler,
|
||||
resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
|
||||
ENDmodInit
|
||||
diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c
|
||||
index 51a9d712a..74437781c 100644
|
||||
--- a/plugins/imudp/imudp.c
|
||||
+++ b/plugins/imudp/imudp.c
|
||||
@@ -152,6 +152,7 @@ struct modConfData_s {
|
||||
int batchSize; /* max nbr of input batch --> also recvmmsg() max count */
|
||||
int8_t wrkrMax; /* max nbr of worker threads */
|
||||
sbool configSetViaV2Method;
|
||||
+ sbool bPreserveCase; /* preserves the case of fromhost; "off" by default */
|
||||
};
|
||||
static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
|
||||
static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
|
||||
@@ -162,7 +163,8 @@ static struct cnfparamdescr modpdescr[] = {
|
||||
{ "schedulingpriority", eCmdHdlrInt, 0 },
|
||||
{ "batchsize", eCmdHdlrInt, 0 },
|
||||
{ "threads", eCmdHdlrPositiveInt, 0 },
|
||||
- { "timerequery", eCmdHdlrInt, 0 }
|
||||
+ { "timerequery", eCmdHdlrInt, 0 },
|
||||
+ { "preservecase", eCmdHdlrBinary, 0 }
|
||||
};
|
||||
static struct cnfparamblk modpblk =
|
||||
{ CNFPARAMBLK_VERSION,
|
||||
@@ -447,8 +449,12 @@ processPacket(struct lstn_s *lstn, struct sockaddr_storage *frominetPrev, int *p
|
||||
if(lstn->dfltTZ != NULL)
|
||||
MsgSetDfltTZ(pMsg, (char*) lstn->dfltTZ);
|
||||
pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME | NEEDS_DNSRESOL;
|
||||
- if(*pbIsPermitted == 2)
|
||||
- pMsg->msgFlags |= NEEDS_ACLCHK_U; /* request ACL check after resolution */
|
||||
+ if(*pbIsPermitted == 2) {
|
||||
+ pMsg->msgFlags |= NEEDS_ACLCHK_U; /* request ACL check after resolution */
|
||||
+ }
|
||||
+ if(runModConf->bPreserveCase) {
|
||||
+ pMsg->msgFlags |= PRESERVE_CASE; /* preserve case of fromhost */
|
||||
+ }
|
||||
CHKiRet(msgSetFromSockinfo(pMsg, frominet));
|
||||
CHKiRet(ratelimitAddMsg(lstn->ratelimiter, multiSub, pMsg));
|
||||
STATSCOUNTER_INC(lstn->ctrSubmit, lstn->mutCtrSubmit);
|
||||
@@ -1030,6 +1036,7 @@ CODESTARTbeginCnfLoad
|
||||
loadModConf->iTimeRequery = TIME_REQUERY_DFLT;
|
||||
loadModConf->iSchedPrio = SCHED_PRIO_UNSET;
|
||||
loadModConf->pszSchedPolicy = NULL;
|
||||
+ loadModConf->bPreserveCase = 0; /* off */
|
||||
bLegacyCnfModGlobalsPermitted = 1;
|
||||
/* init legacy config vars */
|
||||
cs.pszBindRuleset = NULL;
|
||||
@@ -1079,6 +1086,8 @@ CODESTARTsetModCnf
|
||||
} else {
|
||||
loadModConf->wrkrMax = wrkrMax;
|
||||
}
|
||||
+ } else if(!strcmp(modpblk.descr[i].name, "preservecase")) {
|
||||
+ loadModConf->bPreserveCase = (int) pvals[i].val.d.n;
|
||||
} else {
|
||||
dbgprintf("imudp: program error, non-handled "
|
||||
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
|
||||
diff --git a/runtime/msg.c b/runtime/msg.c
|
||||
index c43f81314..9ed4eaf84 100644
|
||||
--- a/runtime/msg.c
|
||||
+++ b/runtime/msg.c
|
||||
@@ -506,7 +506,11 @@ resolveDNS(smsg_t * const pMsg) {
|
||||
MsgLock(pMsg);
|
||||
CHKiRet(objUse(net, CORE_COMPONENT));
|
||||
if(pMsg->msgFlags & NEEDS_DNSRESOL) {
|
||||
- localRet = net.cvthname(pMsg->rcvFrom.pfrominet, &localName, NULL, &ip);
|
||||
+ if (pMsg->msgFlags & PRESERVE_CASE) {
|
||||
+ localRet = net.cvthname(pMsg->rcvFrom.pfrominet, NULL, &localName, &ip);
|
||||
+ } else {
|
||||
+ localRet = net.cvthname(pMsg->rcvFrom.pfrominet, &localName, NULL, &ip);
|
||||
+ }
|
||||
if(localRet == RS_RET_OK) {
|
||||
/* we pass down the props, so no need for AddRef */
|
||||
MsgSetRcvFromWithoutAddRef(pMsg, localName);
|
||||
diff --git a/runtime/msg.h b/runtime/msg.h
|
||||
index cd530aca3..1287cb7a4 100644
|
||||
--- a/runtime/msg.h
|
||||
+++ b/runtime/msg.h
|
||||
@@ -156,6 +156,8 @@ struct msg {
|
||||
/* check UDP ACLs after DNS resolution has been done in main queue consumer */
|
||||
#define NO_PRI_IN_RAW 0x100
|
||||
/* rawmsg does not include a PRI (Solaris!), but PRI is already set correctly in the msg object */
|
||||
+#define PRESERVE_CASE 0x200
|
||||
+/* preserve case in fromhost */
|
||||
|
||||
/* (syslog) protocol types */
|
||||
#define MSG_LEGACY_PROTOCOL 0
|
||||
diff --git a/runtime/net.c b/runtime/net.c
|
||||
index d6ff8a3d4..aef906601 100644
|
||||
--- a/runtime/net.c
|
||||
+++ b/runtime/net.c
|
||||
@@ -1152,7 +1152,7 @@ cvthname(struct sockaddr_storage *f, prop_t **localName, prop_t **fqdn, prop_t *
|
||||
{
|
||||
DEFiRet;
|
||||
assert(f != NULL);
|
||||
- iRet = dnscacheLookup(f, NULL, fqdn, localName, ip);
|
||||
+ iRet = dnscacheLookup(f, fqdn, NULL, localName, ip);
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
diff --git a/runtime/tcpsrv.c b/runtime/tcpsrv.c
|
||||
index 61e9ff4d2..d5993b4f0 100644
|
||||
--- a/runtime/tcpsrv.c
|
||||
+++ b/runtime/tcpsrv.c
|
||||
@@ -495,6 +495,15 @@ SessAccept(tcpsrv_t *pThis, tcpLstnPortList_t *pLstnInfo, tcps_sess_t **ppSess,
|
||||
|
||||
/* get the host name */
|
||||
CHKiRet(netstrm.GetRemoteHName(pNewStrm, &fromHostFQDN));
|
||||
+ if (!pThis->bPreserveCase) {
|
||||
+ /* preserve_case = off */
|
||||
+ uchar *p;
|
||||
+ for(p = fromHostFQDN; *p; p++) {
|
||||
+ if (isupper((int) *p)) {
|
||||
+ *p = tolower((int) *p);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
CHKiRet(netstrm.GetRemoteIP(pNewStrm, &fromHostIP));
|
||||
CHKiRet(netstrm.GetRemAddr(pNewStrm, &addr));
|
||||
/* TODO: check if we need to strip the domain name here -- rgerhards, 2008-04-24 */
|
||||
@@ -1001,6 +1010,7 @@ BEGINobjConstruct(tcpsrv) /* be sure to specify the object type also in END macr
|
||||
pThis->ratelimitBurst = 10000;
|
||||
pThis->bUseFlowControl = 1;
|
||||
pThis->pszDrvrName = NULL;
|
||||
+ pThis->bPreserveCase = 1; /* preserve case in fromhost; default to true. */
|
||||
ENDobjConstruct(tcpsrv)
|
||||
|
||||
|
||||
@@ -1433,6 +1443,16 @@ SetSessMax(tcpsrv_t *pThis, int iMax)
|
||||
}
|
||||
|
||||
|
||||
+static rsRetVal
|
||||
+SetPreserveCase(tcpsrv_t *pThis, int bPreserveCase)
|
||||
+{
|
||||
+ DEFiRet;
|
||||
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
|
||||
+ pThis-> bPreserveCase = bPreserveCase;
|
||||
+ RETiRet;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* queryInterface function
|
||||
* rgerhards, 2008-02-29
|
||||
*/
|
||||
@@ -1491,6 +1511,7 @@ CODESTARTobjQueryInterface(tcpsrv)
|
||||
pIf->SetRuleset = SetRuleset;
|
||||
pIf->SetLinuxLikeRatelimiters = SetLinuxLikeRatelimiters;
|
||||
pIf->SetNotificationOnRemoteClose = SetNotificationOnRemoteClose;
|
||||
+ pIf->SetPreserveCase = SetPreserveCase;
|
||||
|
||||
finalize_it:
|
||||
ENDobjQueryInterface(tcpsrv)
|
||||
diff --git a/runtime/tcpsrv.h b/runtime/tcpsrv.h
|
||||
index 22a65c20a..f17b1b438 100644
|
||||
--- a/runtime/tcpsrv.h
|
||||
+++ b/runtime/tcpsrv.h
|
||||
@@ -85,6 +85,7 @@ struct tcpsrv_s {
|
||||
int maxFrameSize; /**< max frame size for octet counted*/
|
||||
int bDisableLFDelim; /**< if 1, standard LF frame delimiter is disabled (*very dangerous*) */
|
||||
int discardTruncatedMsg;/**< discard msg part that has been truncated*/
|
||||
+ sbool bPreserveCase; /**< preserve case in fromhost */
|
||||
int ratelimitInterval;
|
||||
int ratelimitBurst;
|
||||
tcps_sess_t **pSessions;/**< array of all of our sessions */
|
||||
@@ -177,8 +178,10 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */
|
||||
rsRetVal (*SetbSPFramingFix)(tcpsrv_t*, sbool);
|
||||
/* added v19 -- PascalWithopf, 2017-08-08 */
|
||||
rsRetVal (*SetGnutlsPriorityString)(tcpsrv_t*, uchar*);
|
||||
+ /* added v21 -- Preserve case in fromhost, 2018-08-16 */
|
||||
+ rsRetVal (*SetPreserveCase)(tcpsrv_t *pThis, int bPreserveCase);
|
||||
ENDinterface(tcpsrv)
|
||||
-#define tcpsrvCURR_IF_VERSION 20 /* increment whenever you change the interface structure! */
|
||||
+#define tcpsrvCURR_IF_VERSION 21 /* increment whenever you change the interface structure! */
|
||||
/* change for v4:
|
||||
* - SetAddtlFrameDelim() added -- rgerhards, 2008-12-10
|
||||
* - SetInputName() added -- rgerhards, 2008-12-10
|
@ -1,761 +0,0 @@
|
||||
From 3987cd929d859f900318b393133c3bdde8dfffd5 Mon Sep 17 00:00:00 2001
|
||||
From: Rich Megginson <rmeggins@redhat.com>
|
||||
Date: Tue, 28 Aug 2018 12:44:23 -0600
|
||||
Subject: [PATCH] mmkubertnetes: action fails preparation cycle if kubernetes
|
||||
API destroys resource during bootup sequence
|
||||
|
||||
The plugin was not handling 404 Not Found correctly when looking
|
||||
up pods and namespaces. In this case, we assume the pod/namespace
|
||||
was deleted, annotate the record with whatever metadata we have,
|
||||
and cache the fact that the pod/namespace is missing so we don't
|
||||
attempt to look it up again.
|
||||
In addition, the plugin was not handling error 429 Busy correctly.
|
||||
In this case, it should also annotate the record with whatever
|
||||
metadata it has, and _not_ cache anything. By default the plugin
|
||||
will retry every 5 seconds to connect to Kubernetes. This
|
||||
behavior is controlled by the new config param `busyretryinterval`.
|
||||
This commit also adds impstats counters so that admins can
|
||||
view the state of the plugin to see if the lookups are working
|
||||
or are returning errors. The stats are reported per-instance
|
||||
or per-action to facilitate using multiple different actions
|
||||
for different Kubernetes servers.
|
||||
This commit also adds support for client cert auth to
|
||||
Kubernetes via the two new config params `tls.mycert` and
|
||||
`tls.myprivkey`.
|
||||
---
|
||||
contrib/mmkubernetes/mmkubernetes.c | 296 ++++++++++++++++++++++++----
|
||||
7 files changed, 160 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/contrib/mmkubernetes/mmkubernetes.c b/contrib/mmkubernetes/mmkubernetes.c
|
||||
index 422cb2577..5bf5b049d 100644
|
||||
--- a/contrib/mmkubernetes/mmkubernetes.c
|
||||
+++ b/contrib/mmkubernetes/mmkubernetes.c
|
||||
@@ -52,9 +52,12 @@
|
||||
#include "syslogd-types.h"
|
||||
#include "module-template.h"
|
||||
#include "errmsg.h"
|
||||
+#include "statsobj.h"
|
||||
#include "regexp.h"
|
||||
#include "hashtable.h"
|
||||
#include "srUtils.h"
|
||||
+#include "unicode-helper.h"
|
||||
+#include "datetime.h"
|
||||
|
||||
/* static data */
|
||||
MODULE_TYPE_OUTPUT /* this is technically an output plugin */
|
||||
@@ -62,6 +65,8 @@ MODULE_TYPE_KEEP /* releasing the module would cause a leak through libcurl */
|
||||
MODULE_CNFNAME("mmkubernetes")
|
||||
DEF_OMOD_STATIC_DATA
|
||||
DEFobjCurrIf(regexp)
|
||||
+DEFobjCurrIf(statsobj)
|
||||
+DEFobjCurrIf(datetime)
|
||||
|
||||
#define HAVE_LOADSAMPLESFROMSTRING 1
|
||||
#if defined(NO_LOADSAMPLESFROMSTRING)
|
||||
@@ -95,12 +100,14 @@ DEFobjCurrIf(regexp)
|
||||
#define DFLT_CONTAINER_NAME "$!CONTAINER_NAME" /* name of variable holding CONTAINER_NAME value */
|
||||
#define DFLT_CONTAINER_ID_FULL "$!CONTAINER_ID_FULL" /* name of variable holding CONTAINER_ID_FULL value */
|
||||
#define DFLT_KUBERNETES_URL "https://kubernetes.default.svc.cluster.local:443"
|
||||
+#define DFLT_BUSY_RETRY_INTERVAL 5 /* retry every 5 seconds */
|
||||
|
||||
static struct cache_s {
|
||||
const uchar *kbUrl;
|
||||
struct hashtable *mdHt;
|
||||
struct hashtable *nsHt;
|
||||
pthread_mutex_t *cacheMtx;
|
||||
+ int lastBusyTime;
|
||||
} **caches;
|
||||
|
||||
typedef struct {
|
||||
@@ -116,6 +123,8 @@ struct modConfData_s {
|
||||
uchar *srcMetadataPath; /* where to get data for kubernetes queries */
|
||||
uchar *dstMetadataPath; /* where to put metadata obtained from kubernetes */
|
||||
uchar *caCertFile; /* File holding the CA cert (+optional chain) of CA that issued the Kubernetes server cert */
|
||||
+ uchar *myCertFile; /* File holding cert corresponding to private key used for client cert auth */
|
||||
+ uchar *myPrivKeyFile; /* File holding private key corresponding to cert used for client cert auth */
|
||||
sbool allowUnsignedCerts; /* For testing/debugging - do not check for CA certs (CURLOPT_SSL_VERIFYPEER FALSE) */
|
||||
uchar *token; /* The token value to use to authenticate to Kubernetes - takes precedence over tokenFile */
|
||||
uchar *tokenFile; /* The file whose contents is the token value to use to authenticate to Kubernetes */
|
||||
@@ -127,6 +136,7 @@ struct modConfData_s {
|
||||
uchar *fnRulebase; /* lognorm rulebase filename for container log filename match */
|
||||
char *contRules; /* lognorm rules for CONTAINER_NAME value match */
|
||||
uchar *contRulebase; /* lognorm rulebase filename for CONTAINER_NAME value match */
|
||||
+ int busyRetryInterval; /* how to handle 429 response - 0 means error, non-zero means retry every N seconds */
|
||||
};
|
||||
|
||||
/* action (instance) configuration data */
|
||||
@@ -135,6 +145,8 @@ typedef struct _instanceData {
|
||||
msgPropDescr_t *srcMetadataDescr; /* where to get data for kubernetes queries */
|
||||
uchar *dstMetadataPath; /* where to put metadata obtained from kubernetes */
|
||||
uchar *caCertFile; /* File holding the CA cert (+optional chain) of CA that issued the Kubernetes server cert */
|
||||
+ uchar *myCertFile; /* File holding cert corresponding to private key used for client cert auth */
|
||||
+ uchar *myPrivKeyFile; /* File holding private key corresponding to cert used for client cert auth */
|
||||
sbool allowUnsignedCerts; /* For testing/debugging - do not check for CA certs (CURLOPT_SSL_VERIFYPEER FALSE) */
|
||||
uchar *token; /* The token value to use to authenticate to Kubernetes - takes precedence over tokenFile */
|
||||
uchar *tokenFile; /* The file whose contents is the token value to use to authenticate to Kubernetes */
|
||||
@@ -151,6 +163,7 @@ typedef struct _instanceData {
|
||||
msgPropDescr_t *contNameDescr; /* CONTAINER_NAME field */
|
||||
msgPropDescr_t *contIdFullDescr; /* CONTAINER_ID_FULL field */
|
||||
struct cache_s *cache;
|
||||
+ int busyRetryInterval; /* how to handle 429 response - 0 means error, non-zero means retry every N seconds */
|
||||
} instanceData;
|
||||
|
||||
typedef struct wrkrInstanceData {
|
||||
@@ -159,6 +172,16 @@ typedef struct wrkrInstanceData {
|
||||
struct curl_slist *curlHdr;
|
||||
char *curlRply;
|
||||
size_t curlRplyLen;
|
||||
+ statsobj_t *stats; /* stats for this instance */
|
||||
+ STATSCOUNTER_DEF(k8sRecordSeen, mutK8sRecordSeen)
|
||||
+ STATSCOUNTER_DEF(namespaceMetadataSuccess, mutNamespaceMetadataSuccess)
|
||||
+ STATSCOUNTER_DEF(namespaceMetadataNotFound, mutNamespaceMetadataNotFound)
|
||||
+ STATSCOUNTER_DEF(namespaceMetadataBusy, mutNamespaceMetadataBusy)
|
||||
+ STATSCOUNTER_DEF(namespaceMetadataError, mutNamespaceMetadataError)
|
||||
+ STATSCOUNTER_DEF(podMetadataSuccess, mutPodMetadataSuccess)
|
||||
+ STATSCOUNTER_DEF(podMetadataNotFound, mutPodMetadataNotFound)
|
||||
+ STATSCOUNTER_DEF(podMetadataBusy, mutPodMetadataBusy)
|
||||
+ STATSCOUNTER_DEF(podMetadataError, mutPodMetadataError)
|
||||
} wrkrInstanceData_t;
|
||||
|
||||
/* module parameters (v6 config format) */
|
||||
@@ -167,6 +190,8 @@ static struct cnfparamdescr modpdescr[] = {
|
||||
{ "srcmetadatapath", eCmdHdlrString, 0 },
|
||||
{ "dstmetadatapath", eCmdHdlrString, 0 },
|
||||
{ "tls.cacert", eCmdHdlrString, 0 },
|
||||
+ { "tls.mycert", eCmdHdlrString, 0 },
|
||||
+ { "tls.myprivkey", eCmdHdlrString, 0 },
|
||||
{ "allowunsignedcerts", eCmdHdlrBinary, 0 },
|
||||
{ "token", eCmdHdlrString, 0 },
|
||||
{ "tokenfile", eCmdHdlrString, 0 },
|
||||
@@ -174,7 +199,8 @@ static struct cnfparamdescr modpdescr[] = {
|
||||
{ "de_dot", eCmdHdlrBinary, 0 },
|
||||
{ "de_dot_separator", eCmdHdlrString, 0 },
|
||||
{ "filenamerulebase", eCmdHdlrString, 0 },
|
||||
- { "containerrulebase", eCmdHdlrString, 0 }
|
||||
+ { "containerrulebase", eCmdHdlrString, 0 },
|
||||
+ { "busyretryinterval", eCmdHdlrInt, 0 }
|
||||
#if HAVE_LOADSAMPLESFROMSTRING == 1
|
||||
,
|
||||
{ "filenamerules", eCmdHdlrArray, 0 },
|
||||
@@ -193,6 +219,8 @@ static struct cnfparamdescr actpdescr[] = {
|
||||
{ "srcmetadatapath", eCmdHdlrString, 0 },
|
||||
{ "dstmetadatapath", eCmdHdlrString, 0 },
|
||||
{ "tls.cacert", eCmdHdlrString, 0 },
|
||||
+ { "tls.mycert", eCmdHdlrString, 0 },
|
||||
+ { "tls.myprivkey", eCmdHdlrString, 0 },
|
||||
{ "allowunsignedcerts", eCmdHdlrBinary, 0 },
|
||||
{ "token", eCmdHdlrString, 0 },
|
||||
{ "tokenfile", eCmdHdlrString, 0 },
|
||||
@@ -200,7 +228,8 @@ static struct cnfparamdescr actpdescr[] = {
|
||||
{ "de_dot", eCmdHdlrBinary, 0 },
|
||||
{ "de_dot_separator", eCmdHdlrString, 0 },
|
||||
{ "filenamerulebase", eCmdHdlrString, 0 },
|
||||
- { "containerrulebase", eCmdHdlrString, 0 }
|
||||
+ { "containerrulebase", eCmdHdlrString, 0 },
|
||||
+ { "busyretryinterval", eCmdHdlrInt, 0 }
|
||||
#if HAVE_LOADSAMPLESFROMSTRING == 1
|
||||
,
|
||||
{ "filenamerules", eCmdHdlrArray, 0 },
|
||||
@@ -493,8 +522,9 @@ ENDbeginCnfLoad
|
||||
BEGINsetModCnf
|
||||
struct cnfparamvals *pvals = NULL;
|
||||
int i;
|
||||
- FILE *fp;
|
||||
+ FILE *fp = NULL;
|
||||
int ret;
|
||||
+ char errStr[1024];
|
||||
CODESTARTsetModCnf
|
||||
pvals = nvlstGetParams(lst, &modpblk, NULL);
|
||||
if(pvals == NULL) {
|
||||
@@ -509,6 +539,7 @@ CODESTARTsetModCnf
|
||||
}
|
||||
|
||||
loadModConf->de_dot = DFLT_DE_DOT;
|
||||
+ loadModConf->busyRetryInterval = DFLT_BUSY_RETRY_INTERVAL;
|
||||
for(i = 0 ; i < modpblk.nParams ; ++i) {
|
||||
if(!pvals[i].bUsed) {
|
||||
continue;
|
||||
@@ -528,15 +559,42 @@ CODESTARTsetModCnf
|
||||
loadModConf->caCertFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
fp = fopen((const char*)loadModConf->caCertFile, "r");
|
||||
if(fp == NULL) {
|
||||
- char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
iRet = RS_RET_NO_FILE_ACCESS;
|
||||
LogError(0, iRet,
|
||||
- "error: certificate file %s couldn't be accessed: %s\n",
|
||||
+ "error: 'tls.cacert' file %s couldn't be accessed: %s\n",
|
||||
loadModConf->caCertFile, errStr);
|
||||
ABORT_FINALIZE(iRet);
|
||||
} else {
|
||||
fclose(fp);
|
||||
+ fp = NULL;
|
||||
+ }
|
||||
+ } else if(!strcmp(modpblk.descr[i].name, "tls.mycert")) {
|
||||
+ free(loadModConf->myCertFile);
|
||||
+ loadModConf->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
+ fp = fopen((const char*)loadModConf->myCertFile, "r");
|
||||
+ if(fp == NULL) {
|
||||
+ rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
+ iRet = RS_RET_NO_FILE_ACCESS;
|
||||
+ LogError(0, iRet,
|
||||
+ "error: 'tls.mycert' file %s couldn't be accessed: %s\n",
|
||||
+ loadModConf->myCertFile, errStr);
|
||||
+ } else {
|
||||
+ fclose(fp);
|
||||
+ fp = NULL;
|
||||
+ }
|
||||
+ } else if(!strcmp(modpblk.descr[i].name, "tls.myprivkey")) {
|
||||
+ loadModConf->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
+ fp = fopen((const char*)loadModConf->myPrivKeyFile, "r");
|
||||
+ if(fp == NULL) {
|
||||
+ rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
+ iRet = RS_RET_NO_FILE_ACCESS;
|
||||
+ LogError(0, iRet,
|
||||
+ "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
|
||||
+ loadModConf->myPrivKeyFile, errStr);
|
||||
+ } else {
|
||||
+ fclose(fp);
|
||||
+ fp = NULL;
|
||||
}
|
||||
} else if(!strcmp(modpblk.descr[i].name, "allowunsignedcerts")) {
|
||||
loadModConf->allowUnsignedCerts = pvals[i].val.d.n;
|
||||
@@ -548,7 +606,6 @@ CODESTARTsetModCnf
|
||||
loadModConf->tokenFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
fp = fopen((const char*)loadModConf->tokenFile, "r");
|
||||
if(fp == NULL) {
|
||||
- char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
iRet = RS_RET_NO_FILE_ACCESS;
|
||||
LogError(0, iRet,
|
||||
@@ -557,6 +614,7 @@ CODESTARTsetModCnf
|
||||
ABORT_FINALIZE(iRet);
|
||||
} else {
|
||||
fclose(fp);
|
||||
+ fp = NULL;
|
||||
}
|
||||
} else if(!strcmp(modpblk.descr[i].name, "annotation_match")) {
|
||||
free_annotationmatch(&loadModConf->annotation_match);
|
||||
@@ -577,7 +635,6 @@ CODESTARTsetModCnf
|
||||
loadModConf->fnRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
fp = fopen((const char*)loadModConf->fnRulebase, "r");
|
||||
if(fp == NULL) {
|
||||
- char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
iRet = RS_RET_NO_FILE_ACCESS;
|
||||
LogError(0, iRet,
|
||||
@@ -586,6 +643,7 @@ CODESTARTsetModCnf
|
||||
ABORT_FINALIZE(iRet);
|
||||
} else {
|
||||
fclose(fp);
|
||||
+ fp = NULL;
|
||||
}
|
||||
#if HAVE_LOADSAMPLESFROMSTRING == 1
|
||||
} else if(!strcmp(modpblk.descr[i].name, "containerrules")) {
|
||||
@@ -597,7 +655,6 @@ CODESTARTsetModCnf
|
||||
loadModConf->contRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
fp = fopen((const char*)loadModConf->contRulebase, "r");
|
||||
if(fp == NULL) {
|
||||
- char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
iRet = RS_RET_NO_FILE_ACCESS;
|
||||
LogError(0, iRet,
|
||||
@@ -606,7 +663,10 @@ CODESTARTsetModCnf
|
||||
ABORT_FINALIZE(iRet);
|
||||
} else {
|
||||
fclose(fp);
|
||||
+ fp = NULL;
|
||||
}
|
||||
+ } else if(!strcmp(modpblk.descr[i].name, "busyretryinterval")) {
|
||||
+ loadModConf->busyRetryInterval = pvals[i].val.d.n;
|
||||
} else {
|
||||
dbgprintf("mmkubernetes: program error, non-handled "
|
||||
"param '%s' in module() block\n", modpblk.descr[i].name);
|
||||
@@ -650,6 +710,8 @@ CODESTARTsetModCnf
|
||||
caches = calloc(1, sizeof(struct cache_s *));
|
||||
|
||||
finalize_it:
|
||||
+ if (fp)
|
||||
+ fclose(fp);
|
||||
if(pvals != NULL)
|
||||
cnfparamvalsDestruct(pvals, &modpblk);
|
||||
ENDsetModCnf
|
||||
@@ -667,6 +729,8 @@ CODESTARTfreeInstance
|
||||
free(pData->srcMetadataDescr);
|
||||
free(pData->dstMetadataPath);
|
||||
free(pData->caCertFile);
|
||||
+ free(pData->myCertFile);
|
||||
+ free(pData->myPrivKeyFile);
|
||||
free(pData->token);
|
||||
free(pData->tokenFile);
|
||||
free(pData->fnRules);
|
||||
@@ -710,6 +774,45 @@ CODESTARTcreateWrkrInstance
|
||||
char *tokenHdr = NULL;
|
||||
FILE *fp = NULL;
|
||||
char *token = NULL;
|
||||
+ char *statsName = NULL;
|
||||
+
|
||||
+ CHKiRet(statsobj.Construct(&(pWrkrData->stats)));
|
||||
+ if ((-1 == asprintf(&statsName, "mmkubernetes(%s)", pWrkrData->pData->kubernetesUrl)) ||
|
||||
+ (!statsName)) {
|
||||
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
|
||||
+ }
|
||||
+ CHKiRet(statsobj.SetName(pWrkrData->stats, (uchar *)statsName));
|
||||
+ free(statsName);
|
||||
+ statsName = NULL;
|
||||
+ CHKiRet(statsobj.SetOrigin(pWrkrData->stats, UCHAR_CONSTANT("mmkubernetes")));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->k8sRecordSeen, pWrkrData->mutK8sRecordSeen);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("recordseen"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->k8sRecordSeen)));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataSuccess, pWrkrData->mutNamespaceMetadataSuccess);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatasuccess"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataSuccess)));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataNotFound, pWrkrData->mutNamespaceMetadataNotFound);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatanotfound"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataNotFound)));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataBusy, pWrkrData->mutNamespaceMetadataBusy);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatabusy"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataBusy)));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataError, pWrkrData->mutNamespaceMetadataError);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadataerror"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataError)));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->podMetadataSuccess, pWrkrData->mutPodMetadataSuccess);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatasuccess"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataSuccess)));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->podMetadataNotFound, pWrkrData->mutPodMetadataNotFound);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatanotfound"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataNotFound)));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->podMetadataBusy, pWrkrData->mutPodMetadataBusy);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatabusy"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataBusy)));
|
||||
+ STATSCOUNTER_INIT(pWrkrData->podMetadataError, pWrkrData->mutPodMetadataError);
|
||||
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadataerror"),
|
||||
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataError)));
|
||||
+ CHKiRet(statsobj.ConstructFinalize(pWrkrData->stats));
|
||||
|
||||
hdr = curl_slist_append(hdr, "Content-Type: text/json; charset=utf-8");
|
||||
if (pWrkrData->pData->token) {
|
||||
@@ -749,12 +852,20 @@ CODESTARTcreateWrkrInstance
|
||||
curl_easy_setopt(ctx, CURLOPT_WRITEDATA, pWrkrData);
|
||||
if(pWrkrData->pData->caCertFile)
|
||||
curl_easy_setopt(ctx, CURLOPT_CAINFO, pWrkrData->pData->caCertFile);
|
||||
+ if(pWrkrData->pData->myCertFile)
|
||||
+ curl_easy_setopt(ctx, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile);
|
||||
+ if(pWrkrData->pData->myPrivKeyFile)
|
||||
+ curl_easy_setopt(ctx, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile);
|
||||
if(pWrkrData->pData->allowUnsignedCerts)
|
||||
curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
|
||||
pWrkrData->curlCtx = ctx;
|
||||
finalize_it:
|
||||
free(token);
|
||||
+ free(statsName);
|
||||
+ if ((iRet != RS_RET_OK) && pWrkrData->stats) {
|
||||
+ statsobj.Destruct(&(pWrkrData->stats));
|
||||
+ }
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -765,6 +876,7 @@ BEGINfreeWrkrInstance
|
||||
CODESTARTfreeWrkrInstance
|
||||
curl_easy_cleanup(pWrkrData->curlCtx);
|
||||
curl_slist_free_all(pWrkrData->curlHdr);
|
||||
+ statsobj.Destruct(&(pWrkrData->stats));
|
||||
ENDfreeWrkrInstance
|
||||
|
||||
|
||||
@@ -790,6 +902,8 @@ cacheNew(const uchar *const url)
|
||||
key_equals_string, hashtable_json_object_put);
|
||||
cache->nsHt = create_hashtable(100, hash_from_string,
|
||||
key_equals_string, hashtable_json_object_put);
|
||||
+ dbgprintf("mmkubernetes: created cache mdht [%p] nsht [%p]\n",
|
||||
+ cache->mdHt, cache->nsHt);
|
||||
cache->cacheMtx = malloc(sizeof(pthread_mutex_t));
|
||||
if (!cache->mdHt || !cache->nsHt || !cache->cacheMtx) {
|
||||
free (cache);
|
||||
@@ -797,6 +911,7 @@ cacheNew(const uchar *const url)
|
||||
FINALIZE;
|
||||
}
|
||||
pthread_mutex_init(cache->cacheMtx, NULL);
|
||||
+ cache->lastBusyTime = 0;
|
||||
|
||||
finalize_it:
|
||||
return cache;
|
||||
@@ -816,9 +931,10 @@ static void cacheFree(struct cache_s *cache)
|
||||
BEGINnewActInst
|
||||
struct cnfparamvals *pvals = NULL;
|
||||
int i;
|
||||
- FILE *fp;
|
||||
+ FILE *fp = NULL;
|
||||
char *rxstr = NULL;
|
||||
char *srcMetadataPath = NULL;
|
||||
+ char errStr[1024];
|
||||
CODESTARTnewActInst
|
||||
DBGPRINTF("newActInst (mmkubernetes)\n");
|
||||
|
||||
@@ -840,6 +956,7 @@ CODESTARTnewActInst
|
||||
|
||||
pData->de_dot = loadModConf->de_dot;
|
||||
pData->allowUnsignedCerts = loadModConf->allowUnsignedCerts;
|
||||
+ pData->busyRetryInterval = loadModConf->busyRetryInterval;
|
||||
for(i = 0 ; i < actpblk.nParams ; ++i) {
|
||||
if(!pvals[i].bUsed) {
|
||||
continue;
|
||||
@@ -863,7 +980,6 @@ CODESTARTnewActInst
|
||||
pData->caCertFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
fp = fopen((const char*)pData->caCertFile, "r");
|
||||
if(fp == NULL) {
|
||||
- char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
iRet = RS_RET_NO_FILE_ACCESS;
|
||||
LogError(0, iRet,
|
||||
@@ -872,6 +988,33 @@ CODESTARTnewActInst
|
||||
ABORT_FINALIZE(iRet);
|
||||
} else {
|
||||
fclose(fp);
|
||||
+ fp = NULL;
|
||||
+ }
|
||||
+ } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) {
|
||||
+ pData->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
+ fp = fopen((const char*)pData->myCertFile, "r");
|
||||
+ if(fp == NULL) {
|
||||
+ rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
+ iRet = RS_RET_NO_FILE_ACCESS;
|
||||
+ LogError(0, iRet,
|
||||
+ "error: 'tls.mycert' file %s couldn't be accessed: %s\n",
|
||||
+ pData->myCertFile, errStr);
|
||||
+ } else {
|
||||
+ fclose(fp);
|
||||
+ fp = NULL;
|
||||
+ }
|
||||
+ } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) {
|
||||
+ pData->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
+ fp = fopen((const char*)pData->myPrivKeyFile, "r");
|
||||
+ if(fp == NULL) {
|
||||
+ rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
+ iRet = RS_RET_NO_FILE_ACCESS;
|
||||
+ LogError(0, iRet,
|
||||
+ "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
|
||||
+ pData->myPrivKeyFile, errStr);
|
||||
+ } else {
|
||||
+ fclose(fp);
|
||||
+ fp = NULL;
|
||||
}
|
||||
} else if(!strcmp(actpblk.descr[i].name, "allowunsignedcerts")) {
|
||||
pData->allowUnsignedCerts = pvals[i].val.d.n;
|
||||
@@ -883,7 +1026,6 @@ CODESTARTnewActInst
|
||||
pData->tokenFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
fp = fopen((const char*)pData->tokenFile, "r");
|
||||
if(fp == NULL) {
|
||||
- char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
iRet = RS_RET_NO_FILE_ACCESS;
|
||||
LogError(0, iRet,
|
||||
@@ -892,6 +1034,7 @@ CODESTARTnewActInst
|
||||
ABORT_FINALIZE(iRet);
|
||||
} else {
|
||||
fclose(fp);
|
||||
+ fp = NULL;
|
||||
}
|
||||
} else if(!strcmp(actpblk.descr[i].name, "annotation_match")) {
|
||||
free_annotationmatch(&pData->annotation_match);
|
||||
@@ -912,7 +1055,6 @@ CODESTARTnewActInst
|
||||
pData->fnRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
fp = fopen((const char*)pData->fnRulebase, "r");
|
||||
if(fp == NULL) {
|
||||
- char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
iRet = RS_RET_NO_FILE_ACCESS;
|
||||
LogError(0, iRet,
|
||||
@@ -921,6 +1063,7 @@ CODESTARTnewActInst
|
||||
ABORT_FINALIZE(iRet);
|
||||
} else {
|
||||
fclose(fp);
|
||||
+ fp = NULL;
|
||||
}
|
||||
#if HAVE_LOADSAMPLESFROMSTRING == 1
|
||||
} else if(!strcmp(modpblk.descr[i].name, "containerrules")) {
|
||||
@@ -932,7 +1075,6 @@ CODESTARTnewActInst
|
||||
pData->contRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
fp = fopen((const char*)pData->contRulebase, "r");
|
||||
if(fp == NULL) {
|
||||
- char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
iRet = RS_RET_NO_FILE_ACCESS;
|
||||
LogError(0, iRet,
|
||||
@@ -941,7 +1083,10 @@ CODESTARTnewActInst
|
||||
ABORT_FINALIZE(iRet);
|
||||
} else {
|
||||
fclose(fp);
|
||||
+ fp = NULL;
|
||||
}
|
||||
+ } else if(!strcmp(actpblk.descr[i].name, "busyretryinterval")) {
|
||||
+ pData->busyRetryInterval = pvals[i].val.d.n;
|
||||
} else {
|
||||
dbgprintf("mmkubernetes: program error, non-handled "
|
||||
"param '%s' in action() block\n", actpblk.descr[i].name);
|
||||
@@ -982,6 +1127,10 @@ CODESTARTnewActInst
|
||||
pData->dstMetadataPath = (uchar *) strdup((char *) loadModConf->dstMetadataPath);
|
||||
if(pData->caCertFile == NULL && loadModConf->caCertFile)
|
||||
pData->caCertFile = (uchar *) strdup((char *) loadModConf->caCertFile);
|
||||
+ if(pData->myCertFile == NULL && loadModConf->myCertFile)
|
||||
+ pData->myCertFile = (uchar *) strdup((char *) loadModConf->myCertFile);
|
||||
+ if(pData->myPrivKeyFile == NULL && loadModConf->myPrivKeyFile)
|
||||
+ pData->myPrivKeyFile = (uchar *) strdup((char *) loadModConf->myPrivKeyFile);
|
||||
if(pData->token == NULL && loadModConf->token)
|
||||
pData->token = (uchar *) strdup((char *) loadModConf->token);
|
||||
if(pData->tokenFile == NULL && loadModConf->tokenFile)
|
||||
@@ -1018,6 +1167,8 @@ CODESTARTnewActInst
|
||||
CODE_STD_FINALIZERnewActInst
|
||||
if(pvals != NULL)
|
||||
cnfparamvalsDestruct(pvals, &actpblk);
|
||||
+ if(fp)
|
||||
+ fclose(fp);
|
||||
free(rxstr);
|
||||
free(srcMetadataPath);
|
||||
ENDnewActInst
|
||||
@@ -1061,6 +1212,8 @@ CODESTARTfreeCnf
|
||||
free(pModConf->srcMetadataPath);
|
||||
free(pModConf->dstMetadataPath);
|
||||
free(pModConf->caCertFile);
|
||||
+ free(pModConf->myCertFile);
|
||||
+ free(pModConf->myPrivKeyFile);
|
||||
free(pModConf->token);
|
||||
free(pModConf->tokenFile);
|
||||
free(pModConf->de_dot_separator);
|
||||
@@ -1069,8 +1222,11 @@ CODESTARTfreeCnf
|
||||
free(pModConf->contRules);
|
||||
free(pModConf->contRulebase);
|
||||
free_annotationmatch(&pModConf->annotation_match);
|
||||
- for(i = 0; caches[i] != NULL; i++)
|
||||
+ for(i = 0; caches[i] != NULL; i++) {
|
||||
+ dbgprintf("mmkubernetes: freeing cache [%d] mdht [%p] nsht [%p]\n",
|
||||
+ i, caches[i]->mdHt, caches[i]->nsHt);
|
||||
cacheFree(caches[i]);
|
||||
+ }
|
||||
free(caches);
|
||||
ENDfreeCnf
|
||||
|
||||
@@ -1082,6 +1238,8 @@ CODESTARTdbgPrintInstInfo
|
||||
dbgprintf("\tsrcMetadataPath='%s'\n", pData->srcMetadataDescr->name);
|
||||
dbgprintf("\tdstMetadataPath='%s'\n", pData->dstMetadataPath);
|
||||
dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile);
|
||||
+ dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile);
|
||||
+ dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile);
|
||||
dbgprintf("\tallowUnsignedCerts='%d'\n", pData->allowUnsignedCerts);
|
||||
dbgprintf("\ttoken='%s'\n", pData->token);
|
||||
dbgprintf("\ttokenFile='%s'\n", pData->tokenFile);
|
||||
@@ -1093,6 +1251,7 @@ CODESTARTdbgPrintInstInfo
|
||||
dbgprintf("\tfilenamerules='%s'\n", pData->fnRules);
|
||||
dbgprintf("\tcontainerrules='%s'\n", pData->contRules);
|
||||
#endif
|
||||
+ dbgprintf("\tbusyretryinterval='%d'\n", pData->busyRetryInterval);
|
||||
ENDdbgPrintInstInfo
|
||||
|
||||
|
||||
@@ -1206,6 +1365,24 @@ queryKB(wrkrInstanceData_t *pWrkrData, char *url, struct json_object **rply)
|
||||
struct json_object *jo;
|
||||
long resp_code = 400;
|
||||
|
||||
+ if (pWrkrData->pData->cache->lastBusyTime) {
|
||||
+ time_t now;
|
||||
+ datetime.GetTime(&now);
|
||||
+ now -= pWrkrData->pData->cache->lastBusyTime;
|
||||
+ if (now < pWrkrData->pData->busyRetryInterval) {
|
||||
+ LogMsg(0, RS_RET_RETRY, LOG_DEBUG,
|
||||
+ "mmkubernetes: Waited [%ld] of [%d] seconds for the requested url [%s]\n",
|
||||
+ now, pWrkrData->pData->busyRetryInterval, url);
|
||||
+ ABORT_FINALIZE(RS_RET_RETRY);
|
||||
+ } else {
|
||||
+ LogMsg(0, RS_RET_OK, LOG_DEBUG,
|
||||
+ "mmkubernetes: Cleared busy status after [%d] seconds - "
|
||||
+ "will retry the requested url [%s]\n",
|
||||
+ pWrkrData->pData->busyRetryInterval, url);
|
||||
+ pWrkrData->pData->cache->lastBusyTime = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* query kubernetes for pod info */
|
||||
ccode = curl_easy_setopt(pWrkrData->curlCtx, CURLOPT_URL, url);
|
||||
if(ccode != CURLE_OK)
|
||||
@@ -1238,17 +1415,23 @@ queryKB(wrkrInstanceData_t *pWrkrData, char *url, struct json_object **rply)
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
}
|
||||
if(resp_code == 404) {
|
||||
- LogMsg(0, RS_RET_ERR, LOG_ERR,
|
||||
+ LogMsg(0, RS_RET_NOT_FOUND, LOG_INFO,
|
||||
"mmkubernetes: Not Found: the resource does not exist at url [%s]\n",
|
||||
url);
|
||||
- ABORT_FINALIZE(RS_RET_ERR);
|
||||
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
|
||||
}
|
||||
if(resp_code == 429) {
|
||||
- LogMsg(0, RS_RET_ERR, LOG_ERR,
|
||||
+ if (pWrkrData->pData->busyRetryInterval) {
|
||||
+ time_t now;
|
||||
+ datetime.GetTime(&now);
|
||||
+ pWrkrData->pData->cache->lastBusyTime = now;
|
||||
+ }
|
||||
+
|
||||
+ LogMsg(0, RS_RET_RETRY, LOG_INFO,
|
||||
"mmkubernetes: Too Many Requests: the server is too heavily loaded "
|
||||
"to provide the data for the requested url [%s]\n",
|
||||
url);
|
||||
- ABORT_FINALIZE(RS_RET_ERR);
|
||||
+ ABORT_FINALIZE(RS_RET_RETRY);
|
||||
}
|
||||
if(resp_code != 200) {
|
||||
LogMsg(0, RS_RET_ERR, LOG_ERR,
|
||||
@@ -1299,12 +1482,14 @@ BEGINdoAction
|
||||
char *mdKey = NULL;
|
||||
struct json_object *jMetadata = NULL, *jMetadataCopy = NULL, *jMsgMeta = NULL,
|
||||
*jo = NULL;
|
||||
- int add_ns_metadata = 0;
|
||||
+ int add_pod_metadata = 1;
|
||||
CODESTARTdoAction
|
||||
CHKiRet_Hdlr(extractMsgMetadata(pMsg, pWrkrData->pData, &jMsgMeta)) {
|
||||
ABORT_FINALIZE((iRet == RS_RET_NOT_FOUND) ? RS_RET_OK : iRet);
|
||||
}
|
||||
|
||||
+ STATSCOUNTER_INC(pWrkrData->k8sRecordSeen, pWrkrData->mutK8sRecordSeen);
|
||||
+
|
||||
if (fjson_object_object_get_ex(jMsgMeta, "pod_name", &jo))
|
||||
podName = json_object_get_string(jo);
|
||||
if (fjson_object_object_get_ex(jMsgMeta, "namespace_name", &jo))
|
||||
@@ -1347,28 +1532,49 @@ CODESTARTdoAction
|
||||
}
|
||||
iRet = queryKB(pWrkrData, url, &jReply);
|
||||
free(url);
|
||||
- /* todo: implement support for the .orphaned namespace */
|
||||
- if (iRet != RS_RET_OK) {
|
||||
+ if (iRet == RS_RET_NOT_FOUND) {
|
||||
+ /* negative cache namespace - make a dummy empty namespace metadata object */
|
||||
+ jNsMeta = json_object_new_object();
|
||||
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataNotFound,
|
||||
+ pWrkrData->mutNamespaceMetadataNotFound);
|
||||
+ } else if (iRet == RS_RET_RETRY) {
|
||||
+ /* server is busy - retry or error */
|
||||
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataBusy,
|
||||
+ pWrkrData->mutNamespaceMetadataBusy);
|
||||
+ if (0 == pWrkrData->pData->busyRetryInterval) {
|
||||
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
|
||||
+ ABORT_FINALIZE(RS_RET_ERR);
|
||||
+ }
|
||||
+ add_pod_metadata = 0; /* don't cache pod metadata either - retry both */
|
||||
+ } else if (iRet != RS_RET_OK) {
|
||||
+ /* hard error - something the admin needs to fix e.g. network, config, auth */
|
||||
json_object_put(jReply);
|
||||
jReply = NULL;
|
||||
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataError,
|
||||
+ pWrkrData->mutNamespaceMetadataError);
|
||||
pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
|
||||
FINALIZE;
|
||||
- }
|
||||
-
|
||||
- if(fjson_object_object_get_ex(jReply, "metadata", &jNsMeta)) {
|
||||
+ } else if (fjson_object_object_get_ex(jReply, "metadata", &jNsMeta)) {
|
||||
jNsMeta = json_object_get(jNsMeta);
|
||||
parse_labels_annotations(jNsMeta, &pWrkrData->pData->annotation_match,
|
||||
pWrkrData->pData->de_dot,
|
||||
(const char *)pWrkrData->pData->de_dot_separator,
|
||||
pWrkrData->pData->de_dot_separator_len);
|
||||
- add_ns_metadata = 1;
|
||||
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataSuccess,
|
||||
+ pWrkrData->mutNamespaceMetadataSuccess);
|
||||
} else {
|
||||
/* namespace with no metadata??? */
|
||||
LogMsg(0, RS_RET_ERR, LOG_INFO,
|
||||
"mmkubernetes: namespace [%s] has no metadata!\n", ns);
|
||||
- jNsMeta = NULL;
|
||||
+ /* negative cache namespace - make a dummy empty namespace metadata object */
|
||||
+ jNsMeta = json_object_new_object();
|
||||
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataSuccess,
|
||||
+ pWrkrData->mutNamespaceMetadataSuccess);
|
||||
}
|
||||
|
||||
+ if(jNsMeta) {
|
||||
+ hashtable_insert(pWrkrData->pData->cache->nsHt, strdup(ns), jNsMeta);
|
||||
+ }
|
||||
json_object_put(jReply);
|
||||
jReply = NULL;
|
||||
}
|
||||
@@ -1381,14 +1587,28 @@ CODESTARTdoAction
|
||||
}
|
||||
iRet = queryKB(pWrkrData, url, &jReply);
|
||||
free(url);
|
||||
- if(iRet != RS_RET_OK) {
|
||||
- if(jNsMeta && add_ns_metadata) {
|
||||
- hashtable_insert(pWrkrData->pData->cache->nsHt, strdup(ns), jNsMeta);
|
||||
+ if (iRet == RS_RET_NOT_FOUND) {
|
||||
+ /* negative cache pod - make a dummy empty pod metadata object */
|
||||
+ iRet = RS_RET_OK;
|
||||
+ STATSCOUNTER_INC(pWrkrData->podMetadataNotFound, pWrkrData->mutPodMetadataNotFound);
|
||||
+ } else if (iRet == RS_RET_RETRY) {
|
||||
+ /* server is busy - retry or error */
|
||||
+ STATSCOUNTER_INC(pWrkrData->podMetadataBusy, pWrkrData->mutPodMetadataBusy);
|
||||
+ if (0 == pWrkrData->pData->busyRetryInterval) {
|
||||
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
|
||||
+ ABORT_FINALIZE(RS_RET_ERR);
|
||||
}
|
||||
+ add_pod_metadata = 0; /* do not cache so that we can retry */
|
||||
+ iRet = RS_RET_OK;
|
||||
+ } else if(iRet != RS_RET_OK) {
|
||||
+ /* hard error - something the admin needs to fix e.g. network, config, auth */
|
||||
json_object_put(jReply);
|
||||
jReply = NULL;
|
||||
+ STATSCOUNTER_INC(pWrkrData->podMetadataError, pWrkrData->mutPodMetadataError);
|
||||
pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
|
||||
FINALIZE;
|
||||
+ } else {
|
||||
+ STATSCOUNTER_INC(pWrkrData->podMetadataSuccess, pWrkrData->mutPodMetadataSuccess);
|
||||
}
|
||||
|
||||
jo = json_object_new_object();
|
||||
@@ -1435,11 +1655,9 @@ CODESTARTdoAction
|
||||
json_object_object_add(jo, "container_id", json_object_get(jo2));
|
||||
json_object_object_add(jMetadata, "docker", jo);
|
||||
|
||||
- hashtable_insert(pWrkrData->pData->cache->mdHt, mdKey, jMetadata);
|
||||
- mdKey = NULL;
|
||||
- if(jNsMeta && add_ns_metadata) {
|
||||
- hashtable_insert(pWrkrData->pData->cache->nsHt, strdup(ns), jNsMeta);
|
||||
- ns = NULL;
|
||||
+ if (add_pod_metadata) {
|
||||
+ hashtable_insert(pWrkrData->pData->cache->mdHt, mdKey, jMetadata);
|
||||
+ mdKey = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1450,6 +1668,11 @@ CODESTARTdoAction
|
||||
* outside of the cache lock
|
||||
*/
|
||||
jMetadataCopy = json_tokener_parse(json_object_get_string(jMetadata));
|
||||
+ if (!add_pod_metadata) {
|
||||
+ /* jMetadata object was created from scratch and not cached */
|
||||
+ json_object_put(jMetadata);
|
||||
+ jMetadata = NULL;
|
||||
+ }
|
||||
pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
|
||||
/* the +1 is there to skip the leading '$' */
|
||||
msgAddJSON(pMsg, (uchar *) pWrkrData->pData->dstMetadataPath + 1, jMetadataCopy, 0, 0);
|
||||
@@ -1470,7 +1693,9 @@ BEGINmodExit
|
||||
CODESTARTmodExit
|
||||
curl_global_cleanup();
|
||||
|
||||
+ objRelease(datetime, CORE_COMPONENT);
|
||||
objRelease(regexp, LM_REGEXP_FILENAME);
|
||||
+ objRelease(statsobj, CORE_COMPONENT);
|
||||
ENDmodExit
|
||||
|
||||
|
||||
@@ -1489,8 +1714,9 @@ CODESTARTmodInit
|
||||
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
|
||||
CODEmodInit_QueryRegCFSLineHdlr
|
||||
DBGPRINTF("mmkubernetes: module compiled with rsyslog version %s.\n", VERSION);
|
||||
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
|
||||
CHKiRet(objUse(regexp, LM_REGEXP_FILENAME));
|
||||
-
|
||||
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
|
||||
/* CURL_GLOBAL_ALL initializes more than is needed but the
|
||||
* libcurl documentation discourages use of other values
|
||||
*/
|
@ -1,263 +0,0 @@
|
||||
From e8d64cbd15fa84907dc23f8b52d6f2f847b46fec Mon Sep 17 00:00:00 2001
|
||||
From: Rich Megginson <rmeggins@redhat.com>
|
||||
Date: Mon, 10 Sep 2018 17:25:38 -0600
|
||||
Subject: [PATCH] imfile: support for endmsg.regex
|
||||
|
||||
This adds support for endmsg.regex. It is similar to
|
||||
startmsg.regex except that it matches the line that denotes
|
||||
the end of the message, rather than the start of the next message.
|
||||
This is primarily for container log file use cases such as this:
|
||||
|
||||
date stdout P start of message
|
||||
date stdout P middle of message
|
||||
date stdout F end of message
|
||||
|
||||
The `F` means this is the line which contains the final part of
|
||||
the message. The fully assembled message should be
|
||||
`start of message middle of message end of message`.
|
||||
`startmsg.regex="^[^ ]+ stdout F "` will match.
|
||||
|
||||
(cherry picked from commit c902a0938fe163b5351829d2b72001d024895c16)
|
||||
(cherry picked from commit dd4a72c4d52d8da98ed6b86114868e1a450ccb41)
|
||||
---
|
||||
plugins/imfile/imfile.c | 44 ++++--
|
||||
plugins/imptcp/imptcp.c | 10 +-
|
||||
runtime/stream.c | 28 +++-
|
||||
runtime/stream.h | 2 +-
|
||||
4 files changed, 62 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
|
||||
index 7767c9f02..87706082f 100644
|
||||
--- a/plugins/imfile/imfile.c
|
||||
+++ b/plugins/imfile/imfile.c
|
||||
@@ -126,7 +126,9 @@ struct instanceConf_s {
|
||||
sbool bRMStateOnDel;
|
||||
uint8_t readMode;
|
||||
uchar *startRegex;
|
||||
- regex_t end_preg; /* compiled version of startRegex */
|
||||
+ uchar *endRegex;
|
||||
+ regex_t start_preg; /* compiled version of startRegex */
|
||||
+ regex_t end_preg; /* compiled version of endRegex */
|
||||
sbool discardTruncatedMsg;
|
||||
sbool msgDiscardingError;
|
||||
sbool escapeLF;
|
||||
@@ -281,6 +283,7 @@ static struct cnfparamdescr inppdescr[] = {
|
||||
{ "ruleset", eCmdHdlrString, 0 },
|
||||
{ "readmode", eCmdHdlrInt, 0 },
|
||||
{ "startmsg.regex", eCmdHdlrString, 0 },
|
||||
+ { "endmsg.regex", eCmdHdlrString, 0 },
|
||||
{ "discardtruncatedmsg", eCmdHdlrBinary, 0 },
|
||||
{ "msgdiscardingerror", eCmdHdlrBinary, 0 },
|
||||
{ "escapelf", eCmdHdlrBinary, 0 },
|
||||
@@ -1421,6 +1424,7 @@ pollFileReal(act_obj_t *act, cstr_t **pCStr)
|
||||
int64 strtOffs;
|
||||
DEFiRet;
|
||||
int nProcessed = 0;
|
||||
+ regex_t *start_preg = NULL, *end_preg = NULL;
|
||||
|
||||
DBGPRINTF("pollFileReal enter, pStrm %p, name '%s'\n", act->pStrm, act->name);
|
||||
DBGPRINTF("pollFileReal enter, edge %p\n", act->edge);
|
||||
@@ -1432,15 +1436,18 @@ pollFileReal(act_obj_t *act, cstr_t **pCStr)
|
||||
CHKiRet(openFile(act)); /* open file */
|
||||
}
|
||||
|
||||
+ start_preg = (inst->startRegex == NULL) ? NULL : &inst->start_preg;
|
||||
+ end_preg = (inst->endRegex == NULL) ? NULL : &inst->end_preg;
|
||||
+
|
||||
/* loop below will be exited when strmReadLine() returns EOF */
|
||||
while(glbl.GetGlobalInputTermState() == 0) {
|
||||
if(inst->maxLinesAtOnce != 0 && nProcessed >= inst->maxLinesAtOnce)
|
||||
break;
|
||||
- if(inst->startRegex == NULL) {
|
||||
+ if((start_preg == NULL) && (end_preg == NULL)) {
|
||||
CHKiRet(strm.ReadLine(act->pStrm, pCStr, inst->readMode, inst->escapeLF,
|
||||
inst->trimLineOverBytes, &strtOffs));
|
||||
} else {
|
||||
- CHKiRet(strmReadMultiLine(act->pStrm, pCStr, &inst->end_preg,
|
||||
+ CHKiRet(strmReadMultiLine(act->pStrm, pCStr, start_preg, end_preg,
|
||||
inst->escapeLF, inst->discardTruncatedMsg, inst->msgDiscardingError, &strtOffs));
|
||||
}
|
||||
++nProcessed;
|
||||
@@ -1506,6 +1513,7 @@ createInstance(instanceConf_t **const pinst)
|
||||
inst->iPersistStateInterval = 0;
|
||||
inst->readMode = 0;
|
||||
inst->startRegex = NULL;
|
||||
+ inst->endRegex = NULL;
|
||||
inst->discardTruncatedMsg = 0;
|
||||
inst->msgDiscardingError = 1;
|
||||
inst->bRMStateOnDel = 1;
|
||||
@@ -1713,6 +1721,8 @@ CODESTARTnewInpInst
|
||||
inst->readMode = (sbool) pvals[i].val.d.n;
|
||||
} else if(!strcmp(inppblk.descr[i].name, "startmsg.regex")) {
|
||||
inst->startRegex = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
+ } else if(!strcmp(inppblk.descr[i].name, "endmsg.regex")) {
|
||||
+ inst->endRegex = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
|
||||
} else if(!strcmp(inppblk.descr[i].name, "discardtruncatedmsg")) {
|
||||
inst->discardTruncatedMsg = (sbool) pvals[i].val.d.n;
|
||||
} else if(!strcmp(inppblk.descr[i].name, "msgdiscardingerror")) {
|
||||
@@ -1753,19 +1763,31 @@ CODESTARTnewInpInst
|
||||
"param '%s'\n", inppblk.descr[i].name);
|
||||
}
|
||||
}
|
||||
- if(inst->readMode != 0 && inst->startRegex != NULL) {
|
||||
+ i = (inst->readMode > 0) ? 1 : 0;
|
||||
+ i = (NULL != inst->startRegex) ? (i+1) : i;
|
||||
+ i = (NULL != inst->endRegex) ? (i+1) : i;
|
||||
+ if(i > 1) {
|
||||
LogError(0, RS_RET_PARAM_NOT_PERMITTED,
|
||||
- "readMode and startmsg.regex cannot be set "
|
||||
- "at the same time --- remove one of them");
|
||||
+ "only one of readMode or startmsg.regex or endmsg.regex can be set "
|
||||
+ "at the same time");
|
||||
ABORT_FINALIZE(RS_RET_PARAM_NOT_PERMITTED);
|
||||
}
|
||||
|
||||
if(inst->startRegex != NULL) {
|
||||
- const int errcode = regcomp(&inst->end_preg, (char*)inst->startRegex, REG_EXTENDED);
|
||||
+ const int errcode = regcomp(&inst->start_preg, (char*)inst->startRegex, REG_EXTENDED);
|
||||
+ if(errcode != 0) {
|
||||
+ char errbuff[512];
|
||||
+ regerror(errcode, &inst->start_preg, errbuff, sizeof(errbuff));
|
||||
+ parser_errmsg("imfile: error in startmsg.regex expansion: %s", errbuff);
|
||||
+ ABORT_FINALIZE(RS_RET_ERR);
|
||||
+ }
|
||||
+ }
|
||||
+ if(inst->endRegex != NULL) {
|
||||
+ const int errcode = regcomp(&inst->end_preg, (char*)inst->endRegex, REG_EXTENDED);
|
||||
if(errcode != 0) {
|
||||
char errbuff[512];
|
||||
regerror(errcode, &inst->end_preg, errbuff, sizeof(errbuff));
|
||||
- parser_errmsg("imfile: error in regex expansion: %s", errbuff);
|
||||
+ parser_errmsg("imfile: error in endmsg.regex expansion: %s", errbuff);
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
}
|
||||
}
|
||||
@@ -1970,9 +1992,13 @@ CODESTARTfreeCnf
|
||||
free(inst->pszStateFile);
|
||||
free(inst->pszFileName_forOldStateFile);
|
||||
if(inst->startRegex != NULL) {
|
||||
- regfree(&inst->end_preg);
|
||||
+ regfree(&inst->start_preg);
|
||||
free(inst->startRegex);
|
||||
}
|
||||
+ if(inst->endRegex != NULL) {
|
||||
+ regfree(&inst->end_preg);
|
||||
+ free(inst->endRegex);
|
||||
+ }
|
||||
del = inst;
|
||||
inst = inst->next;
|
||||
free(del);
|
||||
diff --git a/plugins/imptcp/imptcp.c b/plugins/imptcp/imptcp.c
|
||||
index 9b6be0f40..a94b97f41 100644
|
||||
--- a/plugins/imptcp/imptcp.c
|
||||
+++ b/plugins/imptcp/imptcp.c
|
||||
@@ -162,7 +162,7 @@ struct instanceConf_s {
|
||||
int ratelimitInterval;
|
||||
int ratelimitBurst;
|
||||
uchar *startRegex;
|
||||
- regex_t end_preg; /* compiled version of startRegex */
|
||||
+ regex_t start_preg; /* compiled version of startRegex */
|
||||
struct instanceConf_s *next;
|
||||
};
|
||||
|
||||
@@ -961,7 +961,7 @@ processDataRcvd_regexFraming(ptcpsess_t *const __restrict__ pThis,
|
||||
if(c == '\n') {
|
||||
pThis->iCurrLine = pThis->iMsg;
|
||||
} else {
|
||||
- const int isMatch = !regexec(&inst->end_preg, (char*)pThis->pMsg+pThis->iCurrLine, 0, NULL, 0);
|
||||
+ const int isMatch = !regexec(&inst->start_preg, (char*)pThis->pMsg+pThis->iCurrLine, 0, NULL, 0);
|
||||
if(isMatch) {
|
||||
DBGPRINTF("regex match (%d), framing line: %s\n", pThis->iCurrLine, pThis->pMsg);
|
||||
strcpy((char*)pThis->pMsg_save, (char*) pThis->pMsg+pThis->iCurrLine);
|
||||
@@ -2188,10 +2188,10 @@ CODESTARTnewInpInst
|
||||
}
|
||||
|
||||
if(inst->startRegex != NULL) {
|
||||
- const int errcode = regcomp(&inst->end_preg, (char*)inst->startRegex, REG_EXTENDED);
|
||||
+ const int errcode = regcomp(&inst->start_preg, (char*)inst->startRegex, REG_EXTENDED);
|
||||
if(errcode != 0) {
|
||||
char errbuff[512];
|
||||
- regerror(errcode, &inst->end_preg, errbuff, sizeof(errbuff));
|
||||
+ regerror(errcode, &inst->start_preg, errbuff, sizeof(errbuff));
|
||||
parser_errmsg("imptcp: error in framing.delimiter.regex expansion: %s", errbuff);
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
}
|
||||
@@ -2348,7 +2348,7 @@ CODESTARTfreeCnf
|
||||
free(inst->pszInputName);
|
||||
free(inst->dfltTZ);
|
||||
if(inst->startRegex != NULL) {
|
||||
- regfree(&inst->end_preg);
|
||||
+ regfree(&inst->start_preg);
|
||||
free(inst->startRegex);
|
||||
}
|
||||
del = inst;
|
||||
diff --git a/runtime/stream.c b/runtime/stream.c
|
||||
index 6b7e7028e..0f4197103 100644
|
||||
--- a/runtime/stream.c
|
||||
+++ b/runtime/stream.c
|
||||
@@ -942,12 +942,12 @@ strmReadMultiLine_isTimedOut(const strm_t *const __restrict__ pThis)
|
||||
|
||||
/* read a multi-line message from a strm file.
|
||||
* The multi-line message is terminated based on the user-provided
|
||||
- * startRegex (Posix ERE). For performance reasons, the regex
|
||||
+ * startRegex or endRegex (Posix ERE). For performance reasons, the regex
|
||||
* must already have been compiled by the user.
|
||||
* added 2015-05-12 rgerhards
|
||||
*/
|
||||
rsRetVal
|
||||
-strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *preg, const sbool bEscapeLF,
|
||||
+strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *start_preg, regex_t *end_preg, const sbool bEscapeLF,
|
||||
const sbool discardTruncatedMsg, const sbool msgDiscardingError, int64 *const strtOffs)
|
||||
{
|
||||
uchar c;
|
||||
@@ -979,9 +979,14 @@ strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *preg, const sbool bEs
|
||||
cstrFinalize(thisLine);
|
||||
|
||||
/* we have a line, now let's assemble the message */
|
||||
- const int isMatch = !regexec(preg, (char*)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0);
|
||||
-
|
||||
- if(isMatch) {
|
||||
+ const int isStartMatch = start_preg ?
|
||||
+ !regexec(start_preg, (char*)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0) :
|
||||
+ 0;
|
||||
+ const int isEndMatch = end_preg ?
|
||||
+ !regexec(end_preg, (char*)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0) :
|
||||
+ 0;
|
||||
+
|
||||
+ if(isStartMatch) {
|
||||
/* in this case, the *previous* message is complete and we are
|
||||
* at the start of a new one.
|
||||
*/
|
||||
@@ -1047,6 +1052,19 @@ strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *preg, const sbool bEs
|
||||
}
|
||||
}
|
||||
}
|
||||
+ if(isEndMatch) {
|
||||
+ /* in this case, the *current* message is complete and we are
|
||||
+ * at the end of it.
|
||||
+ */
|
||||
+ if(pThis->ignoringMsg == 0) {
|
||||
+ if(pThis->prevMsgSegment != NULL) {
|
||||
+ finished = 1;
|
||||
+ *ppCStr = pThis->prevMsgSegment;
|
||||
+ pThis->prevMsgSegment= NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ pThis->ignoringMsg = 0;
|
||||
+ }
|
||||
cstrDestruct(&thisLine);
|
||||
} while(finished == 0);
|
||||
|
||||
diff --git a/runtime/stream.h b/runtime/stream.h
|
||||
index 71596879e..7dc597ff5 100644
|
||||
--- a/runtime/stream.h
|
||||
+++ b/runtime/stream.h
|
||||
@@ -225,7 +225,7 @@ ENDinterface(strm)
|
||||
/* prototypes */
|
||||
PROTOTYPEObjClassInit(strm);
|
||||
rsRetVal strmMultiFileSeek(strm_t *pThis, unsigned int fileNum, off64_t offs, off64_t *bytesDel);
|
||||
-rsRetVal strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *preg,
|
||||
+rsRetVal strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *start_preg, regex_t *end_preg,
|
||||
sbool bEscapeLF, sbool discardTruncatedMsg, sbool msgDiscardingError, int64 *const strtOffs);
|
||||
int strmReadMultiLine_isTimedOut(const strm_t *const __restrict__ pThis);
|
||||
void strmDebugOutBuf(const strm_t *const pThis);
|
@ -1,368 +0,0 @@
|
||||
From f85ef7aabcec84497a5eaf9670616b3402c79d9c Mon Sep 17 00:00:00 2001
|
||||
From: Rainer Gerhards <rgerhards@adiscon.com>
|
||||
Date: Sun, 23 Sep 2018 13:19:31 +0200
|
||||
Subject: File rotation with imfile broken
|
||||
|
||||
Previously, truncation was only detected at end of file. Especially with
|
||||
busy files that could cause loss of data and possibly also stall imfile
|
||||
reading. The new code now also checks during each read. Obviously, there
|
||||
is some additional overhead associated with that, but this is unavoidable.
|
||||
|
||||
It still is highly recommended NOT to turn on "reopenOnTruncate" in imfile.
|
||||
Note that there are also inherant reliability issues. There is no way to
|
||||
"fix" these, as they are caused by races between the process(es) who truncate
|
||||
and rsyslog reading the file. But with the new code, the "problem window"
|
||||
should be much smaller and, more importantly, imfile should not stall.
|
||||
|
||||
A change in the inode was not detected under all circumstances,
|
||||
most importantly not in some logrotate cases.
|
||||
|
||||
Includes new tests made by Andre Lorbach. They now use the
|
||||
logrotate tool natively to reproduce the issue.
|
||||
---
|
||||
runtime/rsyslog.h | 6 ++--
|
||||
plugins/imfile/imfile.c | 17 +++-
|
||||
runtime/stream.c | 122 ++++++++----
|
||||
runtime/stream.h | 7 ++
|
||||
4 files changed, 126 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
|
||||
index 61d0af623..22a1c46d1 100644
|
||||
--- a/runtime/rsyslog.h
|
||||
+++ b/runtime/rsyslog.h
|
||||
@@ -221,9 +221,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
|
||||
/* begin regular error codes */
|
||||
RS_RET_NOT_IMPLEMENTED = -7, /**< implementation is missing (probably internal error or lazyness ;)) */
|
||||
RS_RET_OUT_OF_MEMORY = -6, /**< memory allocation failed */
|
||||
- RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50,
|
||||
-/*< the caller provided a buffer, but the called function sees the size of this buffer is too small -
|
||||
-operation not carried out */
|
||||
+ RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50, /*< the caller provided a buffer, but the called function sees
|
||||
+ the size of this buffer is too small - operation not carried out */
|
||||
+ RS_RET_FILE_TRUNCATED = -51, /**< (input) file was truncated, not an error but a status */
|
||||
RS_RET_TRUE = -3, /**< to indicate a true state (can be used as TRUE, legacy) */
|
||||
RS_RET_FALSE = -2, /**< to indicate a false state (can be used as FALSE, legacy) */
|
||||
RS_RET_NO_IRET = -8, /**< This is a trick for the debuging system - it means no iRet is provided */
|
||||
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
|
||||
index f4a4ef9b7..6be8b2999 100644
|
||||
--- a/plugins/imfile/imfile.c
|
||||
+++ b/plugins/imfile/imfile.c
|
||||
@@ -740,8 +740,19 @@ detect_updates(fs_edge_t *const edge)
|
||||
act_obj_unlink(act);
|
||||
restart = 1;
|
||||
break;
|
||||
+ } else if(fileInfo.st_ino != act->ino) {
|
||||
+ DBGPRINTF("file '%s' inode changed from %llu to %llu, unlinking from "
|
||||
+ "internal lists\n", act->name, (long long unsigned) act->ino,
|
||||
+ (long long unsigned) fileInfo.st_ino);
|
||||
+ if(act->pStrm != NULL) {
|
||||
+ /* we do no need to re-set later, as act_obj_unlink
|
||||
+ * will destroy the strm obj */
|
||||
+ strmSet_checkRotation(act->pStrm, STRM_ROTATION_DO_NOT_CHECK);
|
||||
+ }
|
||||
+ act_obj_unlink(act);
|
||||
+ restart = 1;
|
||||
+ break;
|
||||
}
|
||||
- // TODO: add inode check for change notification!
|
||||
|
||||
}
|
||||
|
||||
@@ -993,10 +1004,10 @@ chk_active(const act_obj_t *act, const act_obj_t *const deleted)
|
||||
/* unlink act object from linked list and then
|
||||
* destruct it.
|
||||
*/
|
||||
-static void //ATTR_NONNULL()
|
||||
+static void ATTR_NONNULL()
|
||||
act_obj_unlink(act_obj_t *act)
|
||||
{
|
||||
- DBGPRINTF("act_obj_unlink %p: %s\n", act, act->name);
|
||||
+ DBGPRINTF("act_obj_unlink %p: %s, pStrm %p\n", act, act->name, act->pStrm);
|
||||
if(act->prev == NULL) {
|
||||
act->edge->active = act->next;
|
||||
} else {
|
||||
diff --git a/runtime/stream.c b/runtime/stream.c
|
||||
index 0f4197103..32a12b256 100644
|
||||
--- a/runtime/stream.c
|
||||
+++ b/runtime/stream.c
|
||||
@@ -400,6 +400,7 @@ static rsRetVal strmOpenFile(strm_t *pThis)
|
||||
CHKiRet(doPhysOpen(pThis));
|
||||
|
||||
pThis->iCurrOffs = 0;
|
||||
+ pThis->iBufPtrMax = 0;
|
||||
CHKiRet(getFileSize(pThis->pszCurrFName, &offset));
|
||||
if(pThis->tOperationsMode == STREAMMODE_WRITE_APPEND) {
|
||||
pThis->iCurrOffs = offset;
|
||||
@@ -636,6 +637,78 @@ strmHandleEOF(strm_t *pThis)
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
+
|
||||
+/* helper to checkTruncation */
|
||||
+static rsRetVal ATTR_NONNULL()
|
||||
+rereadTruncated(strm_t *const pThis, const char *const reason)
|
||||
+{
|
||||
+ DEFiRet;
|
||||
+
|
||||
+ LogMsg(errno, RS_RET_FILE_TRUNCATED, LOG_WARNING, "file '%s': truncation detected, "
|
||||
+ "(%s) - re-start reading from beginning",
|
||||
+ pThis->pszCurrFName, reason);
|
||||
+ DBGPRINTF("checkTruncation, file %s last buffer CHANGED\n", pThis->pszCurrFName);
|
||||
+ CHKiRet(strmCloseFile(pThis));
|
||||
+ CHKiRet(strmOpenFile(pThis));
|
||||
+ iRet = RS_RET_FILE_TRUNCATED;
|
||||
+
|
||||
+finalize_it:
|
||||
+ RETiRet;
|
||||
+}
|
||||
+/* helper to read:
|
||||
+ * Check if file has been truncated since last read and, if so, re-set reading
|
||||
+ * to begin of file. To detect truncation, we try to re-read the last block.
|
||||
+ * If that does not succeed or different data than from the original read is
|
||||
+ * returned, truncation is assumed.
|
||||
+ * NOTE: this function must be called only if truncation is enabled AND
|
||||
+ * when the previous read buffer still is valid (aka "before the next read").
|
||||
+ * It is ok to call with a 0-size buffer, which we than assume as begin of
|
||||
+ * reading. In that case, no truncation will be detected.
|
||||
+ * rgerhards, 2018-09-20
|
||||
+ */
|
||||
+static rsRetVal ATTR_NONNULL()
|
||||
+checkTruncation(strm_t *const pThis)
|
||||
+{
|
||||
+ DEFiRet;
|
||||
+ int ret;
|
||||
+ off64_t backseek;
|
||||
+ assert(pThis->bReopenOnTruncate);
|
||||
+
|
||||
+ DBGPRINTF("checkTruncation, file %s, iBufPtrMax %zd\n", pThis->pszCurrFName, pThis->iBufPtrMax);
|
||||
+ if(pThis->iBufPtrMax == 0) {
|
||||
+ FINALIZE;
|
||||
+ }
|
||||
+
|
||||
+ int currpos = lseek64(pThis->fd, 0, SEEK_CUR);
|
||||
+ backseek = -1 * (off64_t) pThis->iBufPtrMax;
|
||||
+ dbgprintf("checkTruncation in actual processing, currpos %d, backseek is %d\n", (int)currpos, (int) backseek);
|
||||
+ ret = lseek64(pThis->fd, backseek, SEEK_CUR);
|
||||
+ if(ret < 0) {
|
||||
+ iRet = rereadTruncated(pThis, "cannot seek backward to begin of last block");
|
||||
+ FINALIZE;
|
||||
+ }
|
||||
+dbgprintf("checkTruncation seek backwrds: %d\n", ret);
|
||||
+currpos = lseek64(pThis->fd, 0, SEEK_CUR);
|
||||
+dbgprintf("checkTruncation in actual processing, NEW currpos %d, backseek is %d\n", (int)currpos, (int) backseek);
|
||||
+
|
||||
+ const ssize_t lenRead = read(pThis->fd, pThis->pIOBuf_truncation, pThis->iBufPtrMax);
|
||||
+ dbgprintf("checkTruncation proof-read: %d bytes\n", (int) lenRead);
|
||||
+ if(lenRead < 0) {
|
||||
+ iRet = rereadTruncated(pThis, "last block could not be re-read");
|
||||
+ FINALIZE;
|
||||
+ }
|
||||
+
|
||||
+ if(!memcmp(pThis->pIOBuf_truncation, pThis->pIOBuf, pThis->iBufPtrMax)) {
|
||||
+ DBGPRINTF("checkTruncation, file %s last buffer unchanged\n", pThis->pszCurrFName);
|
||||
+ } else {
|
||||
+ iRet = rereadTruncated(pThis, "last block data different");
|
||||
+ }
|
||||
+
|
||||
+finalize_it:
|
||||
+ RETiRet;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* read the next buffer from disk
|
||||
* rgerhards, 2008-02-13
|
||||
*/
|
||||
@@ -668,6 +741,13 @@ strmReadBuf(strm_t *pThis, int *padBytes)
|
||||
toRead = (size_t) bytesLeft;
|
||||
}
|
||||
}
|
||||
+ if(pThis->bReopenOnTruncate) {
|
||||
+ rsRetVal localRet = checkTruncation(pThis);
|
||||
+ if(localRet == RS_RET_FILE_TRUNCATED) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ CHKiRet(localRet);
|
||||
+ }
|
||||
iLenRead = read(pThis->fd, pThis->pIOBuf, toRead);
|
||||
DBGOPRINT((obj_t*) pThis, "file %d read %ld bytes\n", pThis->fd, iLenRead);
|
||||
/* end crypto */
|
||||
@@ -1184,6 +1264,7 @@ static rsRetVal strmConstructFinalize(strm_t *pThis)
|
||||
} else {
|
||||
/* we work synchronously, so we need to alloc a fixed pIOBuf */
|
||||
CHKmalloc(pThis->pIOBuf = (uchar*) MALLOC(pThis->sIOBufSize));
|
||||
+ CHKmalloc(pThis->pIOBuf_truncation = (char*) MALLOC(pThis->sIOBufSize));
|
||||
}
|
||||
|
||||
finalize_it:
|
||||
@@ -1231,6 +1312,7 @@ CODESTARTobjDestruct(strm)
|
||||
}
|
||||
} else {
|
||||
free(pThis->pIOBuf);
|
||||
+ free(pThis->pIOBuf_truncation);
|
||||
}
|
||||
|
||||
/* Finally, we can free the resources.
|
||||
diff --git a/runtime/stream.c b/runtime/stream.c
|
||||
index 2d494c612..5b52591ef 100644
|
||||
--- a/runtime/stream.c
|
||||
+++ b/runtime/stream.c
|
||||
@@ -360,8 +360,8 @@ CheckFileChange(strm_t *pThis)
|
||||
CHKiRet(strmSetCurrFName(pThis));
|
||||
if(stat((char*) pThis->pszCurrFName, &statName) == -1)
|
||||
ABORT_FINALIZE(RS_RET_IO_ERROR);
|
||||
- DBGPRINTF("stream/after deserialize checking for file change on '%s', "
|
||||
- "inode %u/%u, size/currOffs %llu/%llu\n",
|
||||
+ DBGPRINTF("CheckFileChange: stream/after deserialize checking for file change "
|
||||
+ "on '%s', inode %u/%u, size/currOffs %llu/%llu\n",
|
||||
pThis->pszCurrFName, (unsigned) pThis->inode,
|
||||
(unsigned) statName.st_ino,
|
||||
(long long unsigned) statName.st_size,
|
||||
@@ -574,8 +574,8 @@ strmNextFile(strm_t *pThis)
|
||||
* circumstances). So starting as of now, we only check the inode number and
|
||||
* a file change is detected only if the inode changes. -- rgerhards, 2011-01-10
|
||||
*/
|
||||
-static rsRetVal
|
||||
-strmHandleEOFMonitor(strm_t *pThis)
|
||||
+static rsRetVal ATTR_NONNULL()
|
||||
+strmHandleEOFMonitor(strm_t *const pThis)
|
||||
{
|
||||
DEFiRet;
|
||||
struct stat statName;
|
||||
@@ -611,8 +611,8 @@ strmHandleEOFMonitor(strm_t *pThis)
|
||||
* try to open the next one.
|
||||
* rgerhards, 2008-02-13
|
||||
*/
|
||||
-static rsRetVal
|
||||
-strmHandleEOF(strm_t *pThis)
|
||||
+static rsRetVal ATTR_NONNULL()
|
||||
+strmHandleEOF(strm_t *const pThis)
|
||||
{
|
||||
DEFiRet;
|
||||
|
||||
@@ -629,7 +629,13 @@ strmHandleEOF(strm_t *pThis)
|
||||
CHKiRet(strmNextFile(pThis));
|
||||
break;
|
||||
case STREAMTYPE_FILE_MONITOR:
|
||||
- CHKiRet(strmHandleEOFMonitor(pThis));
|
||||
+ DBGOPRINT((obj_t*) pThis, "file '%s' (%d) EOF, rotationCheck %d\n",
|
||||
+ pThis->pszCurrFName, pThis->fd, pThis->rotationCheck);
|
||||
+ if(pThis->rotationCheck == STRM_ROTATION_DO_CHECK) {
|
||||
+ CHKiRet(strmHandleEOFMonitor(pThis));
|
||||
+ } else {
|
||||
+ ABORT_FINALIZE(RS_RET_EOF);
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -687,9 +693,6 @@ checkTruncation(strm_t *const pThis)
|
||||
iRet = rereadTruncated(pThis, "cannot seek backward to begin of last block");
|
||||
FINALIZE;
|
||||
}
|
||||
-dbgprintf("checkTruncation seek backwrds: %d\n", ret);
|
||||
-currpos = lseek64(pThis->fd, 0, SEEK_CUR);
|
||||
-dbgprintf("checkTruncation in actual processing, NEW currpos %d, backseek is %d\n", (int)currpos, (int) backseek);
|
||||
|
||||
const ssize_t lenRead = read(pThis->fd, pThis->pIOBuf_truncation, pThis->iBufPtrMax);
|
||||
dbgprintf("checkTruncation proof-read: %d bytes\n", (int) lenRead);
|
||||
@@ -861,7 +864,7 @@ static rsRetVal strmUnreadChar(strm_t *pThis, uchar c)
|
||||
* a line, but following lines that are indented are part of the same log entry
|
||||
*/
|
||||
static rsRetVal
|
||||
-strmReadLine(strm_t *pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF,
|
||||
+strmReadLine(strm_t *const pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF,
|
||||
uint32_t trimLineOverBytes, int64 *const strtOffs)
|
||||
{
|
||||
uchar c;
|
||||
@@ -2147,14 +2150,25 @@ DEFpropSetMeth(strm, cryprov, cryprov_if_t*)
|
||||
DEFpropSetMeth(strm, cryprovData, void*)
|
||||
|
||||
/* sets timeout in seconds */
|
||||
-void
|
||||
+void ATTR_NONNULL()
|
||||
strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val)
|
||||
{
|
||||
+ ISOBJ_TYPE_assert(pThis, strm);
|
||||
pThis->readTimeout = val;
|
||||
}
|
||||
|
||||
-static rsRetVal strmSetbDeleteOnClose(strm_t *pThis, int val)
|
||||
+void ATTR_NONNULL()
|
||||
+strmSet_checkRotation(strm_t *const pThis, const int val) {
|
||||
+ ISOBJ_TYPE_assert(pThis, strm);
|
||||
+ assert(val == STRM_ROTATION_DO_CHECK || val == STRM_ROTATION_DO_NOT_CHECK);
|
||||
+ pThis->rotationCheck = val;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static rsRetVal ATTR_NONNULL()
|
||||
+strmSetbDeleteOnClose(strm_t *const pThis, const int val)
|
||||
{
|
||||
+ ISOBJ_TYPE_assert(pThis, strm);
|
||||
pThis->bDeleteOnClose = val;
|
||||
if(pThis->cryprov != NULL) {
|
||||
pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose);
|
||||
@@ -2162,15 +2176,19 @@ static rsRetVal strmSetbDeleteOnClose(strm_t *pThis, int val)
|
||||
return RS_RET_OK;
|
||||
}
|
||||
|
||||
-static rsRetVal strmSetiMaxFiles(strm_t *pThis, int iNewVal)
|
||||
+static rsRetVal ATTR_NONNULL()
|
||||
+strmSetiMaxFiles(strm_t *const pThis, const int iNewVal)
|
||||
{
|
||||
+ ISOBJ_TYPE_assert(pThis, strm);
|
||||
pThis->iMaxFiles = iNewVal;
|
||||
pThis->iFileNumDigits = getNumberDigits(iNewVal);
|
||||
return RS_RET_OK;
|
||||
}
|
||||
|
||||
-static rsRetVal strmSetFileNotFoundError(strm_t *pThis, int pFileNotFoundError)
|
||||
+static rsRetVal ATTR_NONNULL()
|
||||
+strmSetFileNotFoundError(strm_t *const pThis, const int pFileNotFoundError)
|
||||
{
|
||||
+ ISOBJ_TYPE_assert(pThis, strm);
|
||||
pThis->fileNotFoundError = pFileNotFoundError;
|
||||
return RS_RET_OK;
|
||||
}
|
||||
diff --git a/runtime/stream.h b/runtime/stream.h
|
||||
index 7dc597ff5..e3d6c2372 100644
|
||||
--- a/runtime/stream.h
|
||||
+++ b/runtime/stream.h
|
||||
@@ -124,6 +124,7 @@ typedef struct strm_s {
|
||||
ino_t inode; /* current inode for files being monitored (undefined else) */
|
||||
uchar *pszCurrFName; /* name of current file (if open) */
|
||||
uchar *pIOBuf; /* the iobuffer currently in use to gather data */
|
||||
+ char *pIOBuf_truncation; /* iobuffer used during trucation detection block re-reads */
|
||||
size_t iBufPtrMax; /* current max Ptr in Buffer (if partial read!) */
|
||||
size_t iBufPtr; /* pointer into current buffer */
|
||||
int iUngetC; /* char set via UngetChar() call or -1 if none set */
|
||||
|
||||
diff --git a/runtime/stream.h b/runtime/stream.h
|
||||
index e3d6c2372..f6f48378a 100644
|
||||
--- a/runtime/stream.h
|
||||
+++ b/runtime/stream.h
|
||||
@@ -91,6 +91,10 @@ typedef enum { /* when extending, do NOT change existing modes! */
|
||||
STREAMMODE_WRITE_APPEND = 4
|
||||
} strmMode_t;
|
||||
|
||||
+/* settings for stream rotation (applies not to all processing modes!) */
|
||||
+#define STRM_ROTATION_DO_CHECK 0
|
||||
+#define STRM_ROTATION_DO_NOT_CHECK 1
|
||||
+
|
||||
#define STREAM_ASYNC_NUMBUFS 2 /* must be a power of 2 -- TODO: make configurable */
|
||||
/* The strm_t data structure */
|
||||
typedef struct strm_s {
|
||||
@@ -114,6 +118,7 @@ typedef struct strm_s {
|
||||
sbool bDisabled; /* should file no longer be written to? (currently set only if omfile file size limit fails) */
|
||||
sbool bSync; /* sync this file after every write? */
|
||||
sbool bReopenOnTruncate;
|
||||
+ int rotationCheck; /* rotation check mode */
|
||||
size_t sIOBufSize;/* size of IO buffer */
|
||||
uchar *pszDir; /* Directory */
|
||||
int lenDir;
|
||||
@@ -234,5 +239,6 @@ void strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val);
|
||||
const uchar * ATTR_NONNULL() strmGetPrevLineSegment(strm_t *const pThis);
|
||||
const uchar * ATTR_NONNULL() strmGetPrevMsgSegment(strm_t *const pThis);
|
||||
int ATTR_NONNULL() strmGetPrevWasNL(const strm_t *const pThis);
|
||||
+void ATTR_NONNULL() strmSet_checkRotation(strm_t *const pThis, const int val);
|
||||
|
||||
#endif /* #ifndef STREAM_H_INCLUDED */
|
@ -1,86 +0,0 @@
|
||||
From 1255a67fdec2fc44cd49b6ea8c463f4319910812 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Vymazal <jvymazal@redhat.com>
|
||||
Date: Wed, 27 Feb 2019 11:57:49 +0100
|
||||
Subject: [PATCH] Enlarged msg offset types for bigger structured messages
|
||||
|
||||
using a large enough (dozens of kBs) structured message
|
||||
it is possible to overflow the signed short type which leads
|
||||
to rsyslog crash.
|
||||
---
|
||||
runtime/msg.c | 12 ++++++------
|
||||
runtime/msg.h | 8 ++++----
|
||||
2 files changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/runtime/msg.c b/runtime/msg.c
|
||||
index b82c38b9ee..96306bbeab 100644
|
||||
--- a/runtime/msg.c
|
||||
+++ b/runtime/msg.c
|
||||
@@ -839,7 +839,7 @@ msgBaseConstruct(smsg_t **ppThis)
|
||||
pM->iFacility = LOG_INVLD;
|
||||
pM->iLenPROGNAME = -1;
|
||||
pM->offAfterPRI = 0;
|
||||
- pM->offMSG = -1;
|
||||
+ pM->offMSG = 0;
|
||||
pM->iProtocolVersion = 0;
|
||||
pM->msgFlags = 0;
|
||||
pM->iLenRawMsg = 0;
|
||||
@@ -2167,7 +2167,7 @@ MsgSetFlowControlType(smsg_t * const pMsg, flowControl_t eFlowCtl)
|
||||
* rgerhards, 2009-06-16
|
||||
*/
|
||||
rsRetVal
|
||||
-MsgSetAfterPRIOffs(smsg_t * const pMsg, short offs)
|
||||
+MsgSetAfterPRIOffs(smsg_t * const pMsg, uint32_t offs)
|
||||
{
|
||||
assert(pMsg != NULL);
|
||||
pMsg->offAfterPRI = offs;
|
||||
@@ -2819,12 +2819,12 @@ void MsgSetHOSTNAME(smsg_t *pThis, const uchar* pszHOSTNAME, const int lenHOSTNA
|
||||
* (exactly by one). This can happen if we have a message that does not
|
||||
* contain any MSG part.
|
||||
*/
|
||||
-void MsgSetMSGoffs(smsg_t * const pMsg, short offs)
|
||||
+void MsgSetMSGoffs(smsg_t * const pMsg, uint32_t offs)
|
||||
{
|
||||
ISOBJ_TYPE_assert(pMsg, msg);
|
||||
pMsg->offMSG = offs;
|
||||
- if(offs > pMsg->iLenRawMsg) {
|
||||
- assert(offs - 1 == pMsg->iLenRawMsg);
|
||||
+ if(offs > (uint32_t)pMsg->iLenRawMsg) {
|
||||
+ assert((int)offs - 1 == pMsg->iLenRawMsg);
|
||||
pMsg->iLenMSG = 0;
|
||||
} else {
|
||||
pMsg->iLenMSG = pMsg->iLenRawMsg - offs;
|
||||
@@ -2920,7 +2920,7 @@ MsgSetRawMsg(smsg_t *const pThis, const char*const pszRawMsg, const size_t lenMs
|
||||
memcpy(pThis->pszRawMsg, pszRawMsg, pThis->iLenRawMsg);
|
||||
pThis->pszRawMsg[pThis->iLenRawMsg] = '\0'; /* this also works with truncation! */
|
||||
/* correct other information */
|
||||
- if(pThis->iLenRawMsg > pThis->offMSG)
|
||||
+ if((uint32_t)pThis->iLenRawMsg > pThis->offMSG)
|
||||
pThis->iLenMSG += deltaSize;
|
||||
else
|
||||
pThis->iLenMSG = 0;
|
||||
diff --git a/runtime/msg.h b/runtime/msg.h
|
||||
index 74439275b1..722cca6e8a 100644
|
||||
--- a/runtime/msg.h
|
||||
+++ b/runtime/msg.h
|
||||
@@ -67,8 +67,8 @@ struct msg {
|
||||
sbool bParseSuccess; /* set to reflect state of last executed higher level parser */
|
||||
unsigned short iSeverity;/* the severity */
|
||||
unsigned short iFacility;/* Facility code */
|
||||
- short offAfterPRI; /* offset, at which raw message WITHOUT PRI part starts in pszRawMsg */
|
||||
- short offMSG; /* offset at which the MSG part starts in pszRawMsg */
|
||||
+ uint32_t offAfterPRI; /* offset, at which raw message WITHOUT PRI part starts in pszRawMsg */
|
||||
+ uint32_t offMSG; /* offset at which the MSG part starts in pszRawMsg */
|
||||
short iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */
|
||||
int msgFlags; /* flags associated with this message */
|
||||
int iLenRawMsg; /* length of raw message */
|
||||
@@ -194,8 +194,8 @@ void MsgSetRcvFromStr(smsg_t *const pMsg, const uchar* pszRcvFrom, const int, pr
|
||||
rsRetVal MsgSetRcvFromIP(smsg_t *pMsg, prop_t*);
|
||||
rsRetVal MsgSetRcvFromIPStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp);
|
||||
void MsgSetHOSTNAME(smsg_t *pMsg, const uchar* pszHOSTNAME, const int lenHOSTNAME);
|
||||
-rsRetVal MsgSetAfterPRIOffs(smsg_t *pMsg, short offs);
|
||||
-void MsgSetMSGoffs(smsg_t *pMsg, short offs);
|
||||
+rsRetVal MsgSetAfterPRIOffs(smsg_t *pMsg, uint32_t offs);
|
||||
+void MsgSetMSGoffs(smsg_t *pMsg, uint32_t offs);
|
||||
void MsgSetRawMsgWOSize(smsg_t *pMsg, char* pszRawMsg);
|
||||
void ATTR_NONNULL() MsgSetRawMsg(smsg_t *const pThis, const char*const pszRawMsg, const size_t lenMsg);
|
||||
rsRetVal MsgReplaceMSG(smsg_t *pThis, const uchar* pszMSG, int lenMSG);
|
@ -1,58 +0,0 @@
|
||||
From 920c28ff705aac74f389b4613815b14b9482e497 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Vymazal <jvymazal@redhat.com>
|
||||
Date: Mon, 21 Jan 2019 10:58:03 +0100
|
||||
Subject: [PATCH] Added missing free() calls of received journal cursor
|
||||
|
||||
---
|
||||
plugins/imjournal/imjournal.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
|
||||
index a85e521003..f5c2be4b6e 100644
|
||||
--- a/plugins/imjournal/imjournal.c
|
||||
+++ b/plugins/imjournal/imjournal.c
|
||||
@@ -449,6 +449,7 @@ readjournal(void)
|
||||
finalize_it:
|
||||
free(sys_iden_help);
|
||||
free(message);
|
||||
+ free(c);
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
@@ -470,6 +471,7 @@ persistJournalState(void)
|
||||
}
|
||||
} else {
|
||||
int ret;
|
||||
+ free(last_cursor);
|
||||
if ((ret = sd_journal_get_cursor(j, &last_cursor))) {
|
||||
LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_get_cursor() failed");
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
@@ -630,6 +632,7 @@ loadJournalState(void)
|
||||
iRet = RS_RET_ERR;
|
||||
}
|
||||
}
|
||||
+ free(tmp_cursor);
|
||||
}
|
||||
} else {
|
||||
LogError(0, RS_RET_IO_ERROR, "imjournal: "
|
||||
@@ -843,6 +846,7 @@ BEGINfreeCnf
|
||||
free(cs.stateFile);
|
||||
free(cs.usePid);
|
||||
free(cs.dfltTag);
|
||||
+ free(last_cursor);
|
||||
statsobj.Destruct(&(statsCounter.stats));
|
||||
ENDfreeCnf
|
||||
|
||||
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
|
||||
index f5c2be4b6e..7225fae1ab 100644
|
||||
--- a/plugins/imjournal/imjournal.c
|
||||
+++ b/plugins/imjournal/imjournal.c
|
||||
@@ -474,6 +474,7 @@ persistJournalState(void)
|
||||
free(last_cursor);
|
||||
if ((ret = sd_journal_get_cursor(j, &last_cursor))) {
|
||||
LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_get_cursor() failed");
|
||||
+ last_cursor = NULL;
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
Summary: Enhanced system logging and kernel message trapping daemon
|
||||
Name: rsyslog
|
||||
Version: 8.37.0
|
||||
Release: 11%{?dist}
|
||||
Version: 8.1911.0
|
||||
Release: 2%{?dist}
|
||||
License: (GPLv3+ and ASL 2.0)
|
||||
Group: System Environment/Daemons
|
||||
ExcludeArch: i686
|
||||
@ -44,16 +44,10 @@ Provides: syslog
|
||||
Obsoletes: sysklogd < 1.5-11
|
||||
|
||||
# tweak the upstream service file to honour configuration from /etc/sysconfig/rsyslog
|
||||
Patch0: rsyslog-8.32.0-service.patch
|
||||
Patch0: rsyslog-8.1911.0-service.patch
|
||||
# imjournal: adds "journal" when tag/process name is missing
|
||||
Patch1: rsyslog-8.37.0-rhbz1659898-imjournal-default-tag.patch
|
||||
Patch2: rsyslog-8.37.0-rhbz1614179-imfile-symlink-support.patch
|
||||
Patch3: rsyslog-8.37.0-rhbz1622768-kubernetes-404-handling.patch
|
||||
Patch4: rsyslog-8.37.0-rhbz1627941-imfile-support-for-endmsg.regex.patch
|
||||
Patch5: rsyslog-8.37.0-rhbz1674471-imfile-log-rotation.patch
|
||||
Patch6: rsyslog-8.37.0-rhbz1677037-short-offMsg-overrun-crash.patch
|
||||
Patch7: rsyslog-8.37.0-rhbz1614181-imtcp-imudp-preservecase-option.patch
|
||||
Patch8: rsyslog-8.37.0-rhbz1716867-imjournal-memleak.patch
|
||||
Patch1: rsyslog-8.1911.0-rhbz1659898-imjournal-default-tag.patch
|
||||
Patch2: rsyslog-8.1911.0-rhbz1763757-imfile-statefiles.patch
|
||||
|
||||
%package crypto
|
||||
Summary: Encryption support
|
||||
@ -161,8 +155,8 @@ Elasticsearch.
|
||||
|
||||
%description gnutls
|
||||
The rsyslog-gnutls package contains the rsyslog plugins that provide the
|
||||
ability to receive syslog messages via upcoming syslog-transport-tls
|
||||
IETF standard protocol.
|
||||
ability to send and receive syslog messages via TCP or RELP using TLS
|
||||
encryption. For details refer to rsyslog doc on imtcp and omfwd modules.
|
||||
|
||||
%description gssapi
|
||||
The rsyslog-gssapi package contains the rsyslog plugins which support GSSAPI
|
||||
@ -227,13 +221,7 @@ mv build doc
|
||||
|
||||
%patch0 -p1 -b .service
|
||||
%patch1 -p1 -b .default-tag
|
||||
%patch2 -p1 -b .imfile-symlink
|
||||
%patch3 -p1 -b .mmkubernetes-404
|
||||
%patch4 -p1 -b .endmsg-regex
|
||||
%patch5 -p1 -b .rotation-detection
|
||||
%patch6 -p1 -b .short-offmsg-crash
|
||||
%patch7 -p1 -b .preservecase-option
|
||||
%patch8 -p1 -b .imjournal-memleak
|
||||
%patch2 -p1 -b .imfile-statefiles
|
||||
|
||||
%build
|
||||
%ifarch sparc64
|
||||
@ -270,6 +258,7 @@ autoreconf -if
|
||||
--enable-mmsnmptrapd \
|
||||
--enable-mmutf8fix \
|
||||
--enable-mysql \
|
||||
--enable-omhttp \
|
||||
--enable-omjournal \
|
||||
--enable-omkafka \
|
||||
--enable-omprog \
|
||||
@ -361,7 +350,6 @@ done
|
||||
%{_libdir}/rsyslog/lmnetstrms.so
|
||||
%{_libdir}/rsyslog/lmnsd_ptcp.so
|
||||
%{_libdir}/rsyslog/lmregexp.so
|
||||
%{_libdir}/rsyslog/lmstrmsrv.so
|
||||
%{_libdir}/rsyslog/lmtcpclt.so
|
||||
%{_libdir}/rsyslog/lmtcpsrv.so
|
||||
%{_libdir}/rsyslog/lmzlibw.so
|
||||
@ -369,6 +357,7 @@ done
|
||||
%{_libdir}/rsyslog/mmcount.so
|
||||
%{_libdir}/rsyslog/mmexternal.so
|
||||
%{_libdir}/rsyslog/mmutf8fix.so
|
||||
%{_libdir}/rsyslog/omhttp.so
|
||||
%{_libdir}/rsyslog/omjournal.so
|
||||
%{_libdir}/rsyslog/ommail.so
|
||||
%{_libdir}/rsyslog/omprog.so
|
||||
@ -437,6 +426,47 @@ done
|
||||
|
||||
|
||||
%changelog
|
||||
* Tue Dec 03 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.1911.0-2
|
||||
RHEL 8.2.0 ERRATUM
|
||||
- cleaned old patches, fixed patch names
|
||||
resolves: rhbz#1740683
|
||||
|
||||
* Mon Dec 02 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.1911.0-1
|
||||
RHEL 8.2.0 ERRATUM
|
||||
- rebased to 8.1911.0 upstream version, removed, previously
|
||||
upstreamed patches
|
||||
resolves: rhbz#1740683
|
||||
resolves: rhbz#1659383
|
||||
resolves: rhbz#1746876
|
||||
resolves: rhbz#1676559
|
||||
resolves: rhbz#1692072
|
||||
resolves: rhbz#1692073
|
||||
resolves: rhbz#1692074
|
||||
resolves: rhbz#1699242
|
||||
resolves: rhbz#1738213
|
||||
resolves: rhbz#1744691
|
||||
resolves: rhbz#1755218
|
||||
resolves: rhbz#1768321
|
||||
resolves: rhbz#1768324
|
||||
- added patch fixing imfile stefiles naming
|
||||
resolves: rhbz#1763757
|
||||
|
||||
* Fri Aug 30 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.37.0-13
|
||||
RHEL 8.1.0 ERRATUM
|
||||
- added patch enabling stricter TLS certs checking conforming to
|
||||
common criteria requirements
|
||||
resolves: rhbz#1733244
|
||||
|
||||
* Mon Jul 22 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.37.0-12
|
||||
RHEL 8.1.0 ERRATUM
|
||||
- edited imjournal memleak patch to not cause double-free crash
|
||||
resolves: rhbz#1729995
|
||||
- added patch calling journald API only when there are no
|
||||
preceeding errors
|
||||
resolves: rhbz#1722165
|
||||
- added patch fixing imrelp module when invoked with old syntax
|
||||
resolves: rhbz#1724218
|
||||
|
||||
* Wed Jun 05 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.37.0-11
|
||||
RHEL 8.1.0 ERRATUM
|
||||
- fixed memory leak in imjournal by proper cursor releasing
|
||||
|
Loading…
Reference in New Issue
Block a user