diff --git a/README.md b/README.md index 35fbc53..9d1d5fb 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,13 @@ Optional settings A boolean. Specifies whether to extract SYSLOG_STRUCTURED_DATA= from journal. Defaults to false. UseSysLogMsgId= - A boolean. Specifies whether to extract SYSLOG_MSGID= from journal. Defaults to false. + A boolean. Specifies whether to extract SYSLOG_MSGID= from journal. Defaults to false. + + ExcludeSyslogFacility= + A list of strings. Specifies the syslog facilities to skip forwarding. Possible values are: "kern", "user", "mail", "daemon", "auth", "syslog", "lpr", "news", "uucp", "cron", "authpriv", "ftp", "ntp", "security", "console", "solaris-cron", "local0", "local1", "local2", "local3", "local4", "local5", "local6" and "local7". + + ExcludeSyslogLevel= + A list of strings. Specifies the syslog levels to skip forwarding. Possible values are: "emerg", "alert", "crit", "err", "warning", "notice", "info" and "debug". **EXAMPLE** @@ -146,7 +152,18 @@ UseSysLogStructuredData=yes UseSysLogMsgId=yes ``` -Example 5. TLS with certificate authentocation mode +Example 5. Skipping messages with facility AUTH or AUTHPRIV and messages with level DEBUG + +``` toml +[Network] +Address=192.168.8.101:514 +#Protocol=udp +LogFormat=rfc3339 +ExcludeSyslogFacility=auth authpriv +ExcludeSyslogLevel=debug +``` + +Example 6. TLS with certificate authentocation mode ``` toml [Network] @@ -156,7 +173,7 @@ Protocol=tls TLSCertificateAuthMode=warn ``` -Example 6. DTLS with certificate authentocation mode +Example 7. DTLS with certificate authentocation mode ``` toml [Network] diff --git a/conf/netlogd.conf.in b/conf/netlogd.conf.in index 4ebcae8..4103215 100644 --- a/conf/netlogd.conf.in +++ b/conf/netlogd.conf.in @@ -16,3 +16,5 @@ #KeepAliveProbes= #NoDelay=no #SendBuffer= +#ExcludeSyslogFacility= +#ExcludeSyslogLevel= diff --git a/src/netlog/netlog-conf.c b/src/netlog/netlog-conf.c index 48a5ee0..a4cf0da 100644 --- a/src/netlog/netlog-conf.c +++ b/src/netlog/netlog-conf.c @@ -4,6 +4,7 @@ #include "conf-parser.h" #include "def.h" +#include "extract-word.h" #include "in-addr-util.h" #include "netlog-conf.h" #include "parse-util.h" @@ -197,6 +198,90 @@ int config_parse_namespace(const char *unit, return 0; } +int config_parse_syslog_facility(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Manager *m = userdata; + uint32_t val = 0; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + assert(m); + + for (const char *p = rvalue;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= specifier '%s', ignoring: %m", lvalue, rvalue); + return 0; + } + if (r == 0) + break; + + r = syslog_facility_from_string(word); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse syslog facility '%s', ignoring", word); + } else + val |= UINT32_C(1) << r; + } + + m->excluded_syslog_facilities = val; + return 0; +} + +int config_parse_syslog_level(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Manager *m = userdata; + uint8_t val = 0; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + assert(m); + + for (const char *p = rvalue;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= specifier '%s', ignoring: %m", lvalue, rvalue); + return 0; + } + if (r == 0) + break; + + r = syslog_level_from_string(word); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse syslog level '%s', ignoring", word); + } else + val |= UINT8_C(1) << r; + } + + m->excluded_syslog_levels = val; + return 0; +} + int manager_parse_config_file(Manager *m) { int r; diff --git a/src/netlog/netlog-conf.h b/src/netlog/netlog-conf.h index 138c614..6834191 100644 --- a/src/netlog/netlog-conf.h +++ b/src/netlog/netlog-conf.h @@ -62,4 +62,26 @@ int config_parse_namespace(const char *unit, void *data, void *userdata); +int config_parse_syslog_facility(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata); + +int config_parse_syslog_level(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata); + int manager_parse_config_file(Manager *m); diff --git a/src/netlog/netlog-gperf.gperf b/src/netlog/netlog-gperf.gperf index d7836aa..edfd13c 100644 --- a/src/netlog/netlog-gperf.gperf +++ b/src/netlog/netlog-gperf.gperf @@ -32,3 +32,5 @@ Network.KeepAliveIntervalSec, config_parse_sec, 0, off Network.KeepAliveProbes, config_parse_unsigned, 0, offsetof(Manager, keep_alive_cnt) Network.NoDelay, config_parse_bool, 0, offsetof(Manager, no_delay) Network.SendBuffer, config_parse_iec_size, 0, offsetof(Manager, send_buffer) +Network.ExcludeSyslogFacility, config_parse_syslog_facility, 0, offsetof(Manager, excluded_syslog_facilities) +Network.ExcludeSyslogLevel, config_parse_syslog_level, 0, offsetof(Manager, excluded_syslog_levels) diff --git a/src/netlog/netlog-manager.c b/src/netlog/netlog-manager.c index 8bf2d94..7ba18ae 100644 --- a/src/netlog/netlog-manager.c +++ b/src/netlog/netlog-manager.c @@ -35,14 +35,56 @@ static const char *const protocol_table[_SYSLOG_TRANSMISSION_PROTOCOL_MAX] = { [SYSLOG_TRANSMISSION_PROTOCOL_TLS] = "tls", }; -DEFINE_STRING_TABLE_LOOKUP(protocol, int); +DEFINE_STRING_TABLE_LOOKUP(protocol, SysLogTransmissionProtocol); static const char *const log_format_table[_SYSLOG_TRANSMISSION_LOG_FORMAT_MAX] = { [SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5424] = "rfc5424", [SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_3339] = "rfc3339", }; -DEFINE_STRING_TABLE_LOOKUP(log_format, int); +DEFINE_STRING_TABLE_LOOKUP(log_format, SysLogTransmissionLogFormat); + +static const char *const syslog_facility_table[_SYSLOG_FACILITY_MAX] = { + [SYSLOG_FACILITY_KERN] = "kern", + [SYSLOG_FACILITY_USER] = "user", + [SYSLOG_FACILITY_MAIL] = "mail", + [SYSLOG_FACILITY_DAEMON] = "daemon", + [SYSLOG_FACILITY_AUTH] = "auth", + [SYSLOG_FACILITY_SYSLOG] = "syslog", + [SYSLOG_FACILITY_LPR] = "lpr", + [SYSLOG_FACILITY_NEWS] = "news", + [SYSLOG_FACILITY_UUCP] = "uucp", + [SYSLOG_FACILITY_CRON] = "cron", + [SYSLOG_FACILITY_AUTHPRIV] = "authpriv", + [SYSLOG_FACILITY_FTP] = "ftp", + [SYSLOG_FACILITY_NTP] = "ntp", + [SYSLOG_FACILITY_SECURITY] = "security", + [SYSLOG_FACILITY_CONSOLE] = "console", + [SYSLOG_FACILITY_SOLARIS_CRON] = "solaris-cron", + [SYSLOG_FACILITY_LOCAL0] = "local0", + [SYSLOG_FACILITY_LOCAL1] = "local1", + [SYSLOG_FACILITY_LOCAL2] = "local2", + [SYSLOG_FACILITY_LOCAL3] = "local3", + [SYSLOG_FACILITY_LOCAL4] = "local4", + [SYSLOG_FACILITY_LOCAL5] = "local5", + [SYSLOG_FACILITY_LOCAL6] = "local6", + [SYSLOG_FACILITY_LOCAL7] = "local7", +}; + +DEFINE_STRING_TABLE_LOOKUP(syslog_facility, SysLogFacility); + +static const char *const syslog_level_table[_SYSLOG_LEVEL_MAX] = { + [SYSLOG_LEVEL_EMERGENCY] = "emerg", + [SYSLOG_LEVEL_ALERT] = "alert", + [SYSLOG_LEVEL_CRITICAL] = "crit", + [SYSLOG_LEVEL_ERROR] = "err", + [SYSLOG_LEVEL_WARNING] = "warning", + [SYSLOG_LEVEL_NOTICE] = "notice", + [SYSLOG_LEVEL_INFORMATIONAL] = "info", + [SYSLOG_LEVEL_DEBUG] = "debug", +}; + +DEFINE_STRING_TABLE_LOOKUP(syslog_level, SysLogLevel); typedef struct ParseFieldVec { const char *field; @@ -121,7 +163,7 @@ static int manager_read_journal_input(Manager *m) { structured_data_len = 0, msgid_len = 0, pid_len = 0; unsigned sev = JOURNAL_DEFAULT_SEVERITY; unsigned fac = JOURNAL_DEFAULT_FACILITY; - struct timeval tv; + struct timeval tv, *tvp = NULL; const void *data; usec_t realtime; size_t length; @@ -169,14 +211,21 @@ static int manager_read_journal_input(Manager *m) { if (r < 0) log_warning_errno(r, "Failed to rerieve realtime from journal: %m"); else { - tv.tv_sec = realtime / USEC_PER_SEC; - tv.tv_usec = realtime % USEC_PER_SEC; + tv = (struct timeval) { + .tv_sec = realtime / USEC_PER_SEC, + .tv_usec = realtime % USEC_PER_SEC, + }; + tvp = &tv; } if (facility) { r = safe_atou(facility, &fac); if (r < 0) log_debug("Failed to parse syslog facility: %s", facility); + else if (fac < _SYSLOG_FACILITY_MAX && ((UINT32_C(1) << fac) & m->excluded_syslog_facilities)) { + log_debug("Skipping message with excluded syslog facility %s.", syslog_facility_to_string(fac)); + return 0; + } if (fac >= LOG_NFACILITIES) fac = JOURNAL_DEFAULT_FACILITY; @@ -186,6 +235,10 @@ static int manager_read_journal_input(Manager *m) { r = safe_atou(priority, &sev); if (r < 0) log_debug("Failed to parse syslog priority: %s", priority); + else if (sev < _SYSLOG_LEVEL_MAX && ((UINT8_C(1) << sev) & m->excluded_syslog_levels)) { + log_debug("Skipping message with excluded syslog level %s.", syslog_level_to_string(sev)); + return 0; + } if (sev > LOG_DEBUG) sev = JOURNAL_DEFAULT_SEVERITY; @@ -197,7 +250,7 @@ static int manager_read_journal_input(Manager *m) { identifier, message, hostname, pid, - r >= 0 ? &tv : NULL, + tvp, structured_data, m->syslog_msgid ? msgid : NULL); } diff --git a/src/netlog/netlog-manager.h b/src/netlog/netlog-manager.h index ba578c1..48adccb 100644 --- a/src/netlog/netlog-manager.h +++ b/src/netlog/netlog-manager.h @@ -29,6 +29,50 @@ typedef enum SysLogTransmissionLogFormat { _SYSLOG_TRANSMISSION_LOG_FORMAT_INVALID = -EINVAL, } SysLogTransmissionLogFormat; +/* RFC 5424 Section 6.2.1 */ +typedef enum SysLogFacility { + SYSLOG_FACILITY_KERN = 0, + SYSLOG_FACILITY_USER = 1, + SYSLOG_FACILITY_MAIL = 2, + SYSLOG_FACILITY_DAEMON = 3, + SYSLOG_FACILITY_AUTH = 4, + SYSLOG_FACILITY_SYSLOG = 5, + SYSLOG_FACILITY_LPR = 6, + SYSLOG_FACILITY_NEWS = 7, + SYSLOG_FACILITY_UUCP = 8, + SYSLOG_FACILITY_CRON = 9, + SYSLOG_FACILITY_AUTHPRIV = 10, + SYSLOG_FACILITY_FTP = 11, + SYSLOG_FACILITY_NTP = 12, + SYSLOG_FACILITY_SECURITY = 13, + SYSLOG_FACILITY_CONSOLE = 14, + SYSLOG_FACILITY_SOLARIS_CRON = 15, + SYSLOG_FACILITY_LOCAL0 = 16, + SYSLOG_FACILITY_LOCAL1 = 17, + SYSLOG_FACILITY_LOCAL2 = 18, + SYSLOG_FACILITY_LOCAL3 = 19, + SYSLOG_FACILITY_LOCAL4 = 20, + SYSLOG_FACILITY_LOCAL5 = 21, + SYSLOG_FACILITY_LOCAL6 = 22, + SYSLOG_FACILITY_LOCAL7 = 23, + _SYSLOG_FACILITY_MAX, + _SYSLOG_FACILITY_INVALID = -EINVAL, +} SysLogFacility; + +/* RFC 5424 Section 6.2.1 */ +typedef enum SysLogLevel { + SYSLOG_LEVEL_EMERGENCY = 0, + SYSLOG_LEVEL_ALERT = 1, + SYSLOG_LEVEL_CRITICAL = 2, + SYSLOG_LEVEL_ERROR = 3, + SYSLOG_LEVEL_WARNING = 4, + SYSLOG_LEVEL_NOTICE = 5, + SYSLOG_LEVEL_INFORMATIONAL = 6, + SYSLOG_LEVEL_DEBUG = 7, + _SYSLOG_LEVEL_MAX, + _SYSLOG_LEVEL_INVALID = -EINVAL, +} SysLogLevel; + typedef struct Manager Manager; struct Manager { @@ -58,6 +102,9 @@ struct Manager { char *server_name; + uint32_t excluded_syslog_facilities; + uint8_t excluded_syslog_levels; + /* journal */ int journal_watch_fd; int namespace_flags; @@ -119,8 +166,14 @@ int manager_push_to_network(Manager *m, const char *syslog_structured_data, const char *syslog_msgid); -const char *protocol_to_string(int v) _const_; -int protocol_from_string(const char *s) _pure_; +const char *protocol_to_string(SysLogTransmissionProtocol v) _const_; +SysLogTransmissionProtocol protocol_from_string(const char *s) _pure_; + +const char *log_format_to_string(SysLogTransmissionLogFormat v) _const_; +SysLogTransmissionLogFormat log_format_from_string(const char *s) _pure_; + +const char *syslog_facility_to_string(SysLogFacility v) _const_; +SysLogFacility syslog_facility_from_string(const char *s) _pure_; -const char *log_format_to_string(int v) _const_; -int log_format_from_string(const char *s) _pure_; +const char *syslog_level_to_string(SysLogLevel v) _const_; +SysLogLevel syslog_level_from_string(const char *s) _pure_; diff --git a/src/netlog/netlog-tls.c b/src/netlog/netlog-tls.c index 3abc6cb..1f72b0c 100644 --- a/src/netlog/netlog-tls.c +++ b/src/netlog/netlog-tls.c @@ -17,14 +17,14 @@ #include "netlog-ssl.h" -static const char *const certificate_auth_mode_table[OPEN_SSL_CERTIFICATE_AUTH_MODE_MAX] = { +static const char *const certificate_auth_mode_table[_OPEN_SSL_CERTIFICATE_AUTH_MODE_MAX] = { [OPEN_SSL_CERTIFICATE_AUTH_MODE_NONE] = "no", [OPEN_SSL_CERTIFICATE_AUTH_MODE_ALLOW] = "allow", [OPEN_SSL_CERTIFICATE_AUTH_MODE_DENY] = "deny", [OPEN_SSL_CERTIFICATE_AUTH_MODE_WARN] = "warn", }; -DEFINE_STRING_TABLE_LOOKUP(certificate_auth_mode, int); +DEFINE_STRING_TABLE_LOOKUP(certificate_auth_mode, OpenSSLCertificateAuthMode); static int tls_write(TLSManager *m, const char *buf, size_t count) { int r; diff --git a/src/netlog/netlog-tls.h b/src/netlog/netlog-tls.h index 6f3fd69..35eaece 100644 --- a/src/netlog/netlog-tls.h +++ b/src/netlog/netlog-tls.h @@ -8,11 +8,12 @@ #include "openssl-util.h" typedef enum OpenSSLCertificateAuthMode { - OPEN_SSL_CERTIFICATE_AUTH_MODE_NONE = 1 << 0, - OPEN_SSL_CERTIFICATE_AUTH_MODE_ALLOW = 1 << 1, - OPEN_SSL_CERTIFICATE_AUTH_MODE_DENY = 1 << 2, - OPEN_SSL_CERTIFICATE_AUTH_MODE_WARN = 1 << 3, - OPEN_SSL_CERTIFICATE_AUTH_MODE_MAX = 1 << 4, + OPEN_SSL_CERTIFICATE_AUTH_MODE_NONE = 0, + OPEN_SSL_CERTIFICATE_AUTH_MODE_ALLOW = 1, + OPEN_SSL_CERTIFICATE_AUTH_MODE_DENY = 2, + OPEN_SSL_CERTIFICATE_AUTH_MODE_WARN = 3, + _OPEN_SSL_CERTIFICATE_AUTH_MODE_MAX, + _OPEN_SSL_CERTIFICATE_AUTH_MODE_INVALID = -EINVAL, } OpenSSLCertificateAuthMode; typedef struct TLSManager TLSManager; @@ -36,8 +37,8 @@ void tls_disconnect(TLSManager *m); int tls_stream_writev(TLSManager *m, const struct iovec *iov, size_t iovcnt); -const char *certificate_auth_mode_to_string(int v) _const_; -int certificate_auth_mode_from_string(const char *s) _pure_; +const char *certificate_auth_mode_to_string(OpenSSLCertificateAuthMode v) _const_; +OpenSSLCertificateAuthMode certificate_auth_mode_from_string(const char *s) _pure_; DEFINE_TRIVIAL_CLEANUP_FUNC(TLSManager*, tls_manager_free);