diff --git a/src/confd/src/ietf-syslog.c b/src/confd/src/ietf-syslog.c index d3c3d320..09d52f70 100644 --- a/src/confd/src/ietf-syslog.c +++ b/src/confd/src/ietf-syslog.c @@ -118,6 +118,40 @@ static size_t selector(sr_session_ctx_t *session, struct action *act) count = 0; } + /* Check for property-filter (infix-syslog augment) */ + char *property = srx_get_str(session, "%s/infix-syslog:property-filter/property", act->xpath); + if (property) { + char *operator = srx_get_str(session, "%s/infix-syslog:property-filter/operator", act->xpath); + char *value = srx_get_str(session, "%s/infix-syslog:property-filter/value", act->xpath); + char *case_str = srx_get_str(session, "%s/infix-syslog:property-filter/case-insensitive", act->xpath); + char *negate_str = srx_get_str(session, "%s/infix-syslog:property-filter/negate", act->xpath); + + if (operator && value) { + /* Build operator prefix: [!][icase_]operator */ + char op_prefix[32] = ""; + + /* Only apply negate if explicitly set to true */ + if (negate_str && !strcmp(negate_str, "true")) + strlcat(op_prefix, "!", sizeof(op_prefix)); + + /* Only apply icase_ if explicitly set to true */ + if (case_str && !strcmp(case_str, "true")) + strlcat(op_prefix, "icase_", sizeof(op_prefix)); + + strlcat(op_prefix, operator, sizeof(op_prefix)); + + /* Property-based filter: :property, [!][icase_]operator, "value" */ + fprintf(act->fp, ":%s, %s, \"%s\"\n", property, op_prefix, value); + has_pattern = true; + } + + free(property); + free(operator); + free(value); + free(case_str); + free(negate_str); + } + /* Check for pattern-match (select-match feature) */ pattern = srx_get_str(session, "%s/pattern-match", act->xpath); if (pattern) { diff --git a/src/confd/yang/confd/infix-syslog.yang b/src/confd/yang/confd/infix-syslog.yang index 72d5124f..981f498d 100644 --- a/src/confd/yang/confd/infix-syslog.yang +++ b/src/confd/yang/confd/infix-syslog.yang @@ -175,6 +175,83 @@ module infix-syslog { description "Filter messages by hostname. Messages from the listed hostnames will be logged to this file."; } + + container property-filter { + presence "Enable property-based filtering"; + description "Advanced property-based message filtering. Allows filtering + on specific message fields with various comparison operators."; + + leaf property { + type enumeration { + enum msg { + description "The message body (SYSLOG-MSG field)."; + } + enum msgid { + description "The RFC5424 message identifier (MSGID field)."; + } + enum programname { + description "The originating program or tag name."; + } + enum hostname { + description "The message source hostname."; + } + enum source { + description "The message source (alias for hostname)."; + } + enum data { + description "The RFC5424 structured data (SD field)."; + } + } + mandatory true; + description "The message property to match against."; + } + + leaf operator { + type enumeration { + enum contains { + description "Substring match (case-sensitive)."; + } + enum isequal { + description "Exact equality match."; + } + enum startswith { + description "Prefix match."; + } + enum regex { + description "Basic regular expression match."; + } + enum ereregex { + description "Extended regular expression match (POSIX ERE)."; + } + } + mandatory true; + description "The comparison operator to use."; + } + + leaf value { + type string; + mandatory true; + description "The value to compare against."; + } + + leaf case-insensitive { + type boolean; + description "Perform case-insensitive comparison."; + } + + leaf negate { + type boolean; + description "Negate the comparison result. When set to true, the + filter matches messages that do NOT satisfy the + specified condition. + + For example: + - operator: contains, value: 'ERROR', negate: false + → matches messages containing 'ERROR' + - operator: contains, value: 'ERROR', negate: true + → matches messages NOT containing 'ERROR'"; + } + } } augment "/syslog:syslog/syslog:actions/syslog:remote/syslog:destination" {