[PATCH 1/2] syslogd: add ability to filter based on start of message

Alexander Vickberg wickbergster at gmail.com
Mon Mar 15 11:27:15 UTC 2021


Signed-off-by: Alexander Vickberg <wickbergster at gmail.com>
---
 sysklogd/syslogd.c | 74 +++++++++++++++++++++++++++++++---------------
 1 file changed, 50 insertions(+), 24 deletions(-)

diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 6ddfd771a..d1ecf5e5e 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -227,10 +227,18 @@ typedef struct logFile_t {
 } logFile_t;
 
 #if ENABLE_FEATURE_SYSLOGD_CFG
+typedef struct stringMatch_t {
+	char *str;
+	int len;
+	uint8_t enabled_priomap;
+	struct stringMatch_t *prev;
+} stringMatch_t;
+
 typedef struct logRule_t {
 	uint8_t enabled_facility_priomap[LOG_NFACILITIES];
 	struct logFile_t *file;
-	struct logRule_t *next;
+	struct stringMatch_t *strmatch;
+	struct logRule_t *prev;
 } logRule_t;
 #endif
 
@@ -394,7 +402,6 @@ static const CODE* find_by_val(int val, const CODE* c_set)
 static void parse_syslogdcfg(const char *file)
 {
 	char *t;
-	logRule_t **pp_rule;
 	/* tok[0] set of selectors */
 	/* tok[1] file name */
 	/* tok[2] has to be NULL */
@@ -408,18 +415,18 @@ static void parse_syslogdcfg(const char *file)
 		/* proceed as if we built busybox without config support */
 		return;
 
-	/* use ptr to ptr to avoid checking whether head was initialized */
-	pp_rule = &G.log_rules;
 	/* iterate through lines of config, skipping comments */
 	while (config_read(parser, tok, 3, 2, "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) {
 		char *cur_selector;
-		logRule_t *cur_rule;
+		logRule_t *cur_rule, *tmp;
 
 		/* unexpected trailing token? */
 		if (tok[2])
 			goto cfgerr;
 
-		cur_rule = *pp_rule = xzalloc(sizeof(*cur_rule));
+		cur_rule = xzalloc(sizeof(*cur_rule));
+		cur_rule->prev = G.log_rules;
+		G.log_rules = cur_rule;
 
 		cur_selector = tok[0];
 		/* iterate through selectors: "kern.info;kern.!err;..." */
@@ -491,11 +498,28 @@ static void parse_syslogdcfg(const char *file)
 					if (next_facility)
 						*next_facility++ = '\0';
 					code = find_by_name(t, bb_facilitynames);
-					if (!code)
-						goto cfgerr;
-					/* "mark" is not a real facility, skip it */
-					if (code->c_val != INTERNAL_MARK)
-						facmap |= 1<<(LOG_FAC(code->c_val));
+					if (code) {
+						/* "mark" is not a real facility, skip it */
+						if (code->c_val != INTERNAL_MARK)
+							facmap |= 1<<(LOG_FAC(code->c_val));
+					} else { /* Treat this as string match filter */
+						stringMatch_t *strmatch;
+						/* Merge if previously found */
+						for (strmatch = cur_rule->strmatch; strmatch; strmatch = strmatch->prev)
+							if (!strcmp(strmatch->str, t))
+								break;
+						if (!strmatch) {
+							strmatch = xzalloc(sizeof(struct stringMatch_t));
+							strmatch->str = xstrdup(t);
+							strmatch->len = strlen(t);
+							strmatch->prev = cur_rule->strmatch;
+							cur_rule->strmatch = strmatch;
+						}
+						if (negated_prio)
+							strmatch->enabled_priomap &= primap;
+						else
+							strmatch->enabled_priomap |= primap;
+					}
 					t = next_facility;
 				} while (t);
 			}
@@ -518,25 +542,19 @@ static void parse_syslogdcfg(const char *file)
 		 */
 		if (strcmp(G.logFile.path, tok[1]) == 0) {
 			cur_rule->file = &G.logFile;
-			goto found;
+			continue;
 		}
-		/* temporarily use cur_rule as iterator, but *pp_rule still points
-		 * to currently processing rule entry.
-		 * NOTE: *pp_rule points to the current (and last in the list) rule.
-		 */
-		for (cur_rule = G.log_rules; cur_rule != *pp_rule; cur_rule = cur_rule->next) {
-			if (strcmp(cur_rule->file->path, tok[1]) == 0) {
+
+		for (tmp = cur_rule->prev; tmp; tmp = tmp->prev) {
+			if (strcmp(tmp->file->path, tok[1]) == 0) {
 				/* found - reuse the same file structure */
-				(*pp_rule)->file = cur_rule->file;
-				cur_rule = *pp_rule;
-				goto found;
+				cur_rule->file = tmp->file;
+				continue;
 			}
 		}
 		cur_rule->file = xzalloc(sizeof(*cur_rule->file));
 		cur_rule->file->fd = -1;
 		cur_rule->file->path = xstrdup(tok[1]);
- found:
-		pp_rule = &cur_rule->next;
 	}
 	config_close(parser);
 	return;
@@ -879,10 +897,18 @@ static void timestamp_and_log(int pri, char *msg, int len)
 		uint8_t facility = LOG_FAC(pri);
 		uint8_t prio_bit = 1 << LOG_PRI(pri);
 
-		for (rule = G.log_rules; rule; rule = rule->next) {
+		for (rule = G.log_rules; rule; rule = rule->prev) {
 			if (rule->enabled_facility_priomap[facility] & prio_bit) {
 				log_locally(now, G.printbuf, rule->file);
 				match = 1;
+			} else { /* check if message starts with any string in list rule->strmatch */
+				stringMatch_t *strmatch;
+				for (strmatch = rule->strmatch; strmatch; strmatch = strmatch->prev) {
+					if (!memcmp(strmatch->str, msg, strmatch->len) && strmatch->enabled_priomap & prio_bit) {
+						log_locally(now, G.printbuf, rule->file);
+						match = 1;
+					}
+				}
 			}
 		}
 		if (match)
-- 
2.25.1



More information about the busybox mailing list