2017-08-27 10:11:05 +00:00
######################################################################################################################
2018-08-01 19:20:56 +00:00
# $Id: 93_Log2Syslog.pm 16688 2018-05-04 20:09:12Z DS_Starter $
2017-08-27 10:11:05 +00:00
######################################################################################################################
2017-08-16 22:32:44 +00:00
# 93_Log2Syslog.pm
#
2018-08-01 19:20:56 +00:00
# (c) 2017-2018 by Heiko Maaz
2017-08-16 22:32:44 +00:00
# e-mail: Heiko dot Maaz at t-online dot de
#
# This script is part of fhem.
#
# Fhem is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# Fhem is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with fhem. If not, see <http://www.gnu.org/licenses/>.
#
2018-08-01 19:20:56 +00:00
# The module is based on idea and input from betateilchen 92_rsyslog.pm
2017-08-25 08:28:14 +00:00
#
2017-08-17 20:20:38 +00:00
# Implements the Syslog Protocol of RFC 5424 https://tools.ietf.org/html/rfc5424
2017-08-25 08:28:14 +00:00
# and RFC 3164 https://tools.ietf.org/html/rfc3164 and
# TLS Transport according to RFC5425 https://tools.ietf.org/pdf/rfc5425.pdf as well
2017-08-16 22:32:44 +00:00
#
2017-08-27 10:11:05 +00:00
######################################################################################################################
2017-08-16 22:32:44 +00:00
# Versions History:
#
2018-08-15 06:15:18 +00:00
# 4.8.4 15.08.2018 BSD parsing changed
2018-08-14 20:44:57 +00:00
# 4.8.3 14.08.2018 BSD setpayload changed, BSD parsing changed, Internal MYFQDN
# 4.8.2 13.08.2018 rename makeMsgEvent to makeEvent
2018-08-12 18:57:45 +00:00
# 4.8.1 12.08.2018 IETF-Syslog without VERSION changed, Log verbose 1 to 2 changed in parsePayload
2018-08-12 16:16:31 +00:00
# 4.8.0 12.08.2018 enhanced IETF Parser to match logs without version
2018-08-10 12:40:19 +00:00
# 4.7.0 10.08.2018 Parser for TPLink
2018-08-10 10:23:13 +00:00
# 4.6.1 10.08.2018 some perl warnings, changed IETF Parser
2018-08-13 21:55:35 +00:00
# 4.6.0 08.08.2018 set sendTestMessage added, Attribute "contDelimiter", "respectSeverity"
2018-08-07 20:54:44 +00:00
# 4.5.1 07.08.2018 BSD Regex changed, setpayload of BSD changed
2018-08-06 21:02:42 +00:00
# 4.5.0 06.08.2018 Regex capture groups used in parsePayload to set variables, parsing of BSD changed,
# Attribute "makeMsgEvent" added
2018-08-05 19:04:41 +00:00
# 4.4.0 04.08.2018 Attribute "outputFields" added
# 4.3.0 03.08.2018 Attribute "parseFn" added
2018-08-03 08:57:49 +00:00
# 4.2.0 03.08.2018 evaluate sender peer ip-address/hostname, use it as reading in event generation
# 4.1.0 02.08.2018 state event generation changed
# 4.0.0 30.07.2018 server mode (Collector)
2018-08-01 19:20:56 +00:00
# 3.2.1 04.05.2018 fix compatibility with newer IO::Socket::SSL on debian 9, attr ssldebug for
# debugging SSL messages
# 3.2.0 22.11.2017 add NOTIFYDEV if possible
# 3.1.0 28.08.2017 get-function added, commandref revised, $readingFnAttributes deleted
2017-08-27 10:11:05 +00:00
# 3.0.0 27.08.2017 change attr type to protocol, ready to check in
# 2.6.0 26.08.2017 more than one Log2Syslog device can be created
# 2.5.2 26.08.2018 fix in splitting timestamp, change Log2Syslog_trate using internaltimer with attr
2017-08-27 10:50:18 +00:00
# rateCalcRerun, function Log2Syslog_closesock
2017-08-25 08:28:14 +00:00
# 2.5.1 24.08.2017 some fixes
# 2.5.0 23.08.2017 TLS encryption available, new readings, $readingFnAttributes
2017-08-27 10:11:05 +00:00
# 2.4.1 21.08.2017 changes in sub Log2Syslog_charfilter, change PROCID to $hash->{SEQNO}
# switch to non-blocking in subs event/Log2Syslog_fhemlog
# 2.4.0 20.08.2017 new sub Log2Syslog_Log3slog for entries in local fhemlog only -> verbose support
2017-08-19 15:09:53 +00:00
# 2.3.1 19.08.2017 commandref revised
2017-08-27 10:11:05 +00:00
# 2.3.0 18.08.2017 new parameter "ident" in DEF, sub setidex, Log2Syslog_charfilter
2017-08-17 20:20:38 +00:00
# 2.2.0 17.08.2017 set BSD data length, set only acceptable characters (USASCII) in payload
# commandref revised
2018-08-08 20:51:50 +00:00
# 2.1.0 17.08.2017 sub Log2Syslog_opensock created
2017-08-16 22:32:44 +00:00
# 2.0.0 16.08.2017 create syslog without SYS::SYSLOG
2017-08-27 10:11:05 +00:00
# 1.1.1 13.08.2017 registrate Log2Syslog_fhemlog to %loginform in case of sending fhem-log
2017-08-16 22:32:44 +00:00
# attribute timeout, commandref revised
2017-08-27 10:11:05 +00:00
# 1.1.0 26.07.2017 add regex search to sub Log2Syslog_fhemlog
2017-08-16 22:32:44 +00:00
# 1.0.0 25.07.2017 initial version
package main ;
use strict ;
use warnings ;
2018-08-06 20:07:30 +00:00
use Scalar::Util qw( looks_like_number ) ;
2018-08-01 19:20:56 +00:00
use Encode qw( encode_utf8 ) ;
2018-08-13 21:55:35 +00:00
use Net::Domain qw( hostname hostfqdn hostdomain ) ;
2017-08-16 22:32:44 +00:00
eval "use IO::Socket::INET;1" or my $ MissModulSocket = "IO::Socket::INET" ;
2018-08-01 19:20:56 +00:00
eval "use Net::Domain qw(hostname hostfqdn hostdomain domainname);1" or my $ MissModulNDom = "Net::Domain" ;
2017-08-16 22:32:44 +00:00
2017-08-27 10:11:05 +00:00
###############################################################################
2017-08-20 08:19:32 +00:00
# Forward declarations
#
2017-08-27 10:11:05 +00:00
sub Log2Syslog_Log3slog ($$$) ;
2017-08-20 08:19:32 +00:00
2018-08-15 06:15:18 +00:00
my $ Log2SyslogVn = "4.8.4" ;
2017-08-16 22:32:44 +00:00
# Mappinghash BSD-Formatierung Monat
my % Log2Syslog_BSDMonth = (
"01" = > "Jan" ,
"02" = > "Feb" ,
"03" = > "Mar" ,
"04" = > "Apr" ,
"05" = > "May" ,
"06" = > "Jun" ,
"07" = > "Jul" ,
"08" = > "Aug" ,
"09" = > "Sep" ,
"10" = > "Oct" ,
"11" = > "Nov" ,
2018-08-01 19:20:56 +00:00
"12" = > "Dec" ,
"Jan" = > "01" ,
"Feb" = > "02" ,
"Mar" = > "03" ,
"Apr" = > "04" ,
"May" = > "05" ,
"Jun" = > "06" ,
"Jul" = > "07" ,
"Aug" = > "08" ,
"Sep" = > "09" ,
"Oct" = > "10" ,
"Nov" = > "11" ,
2018-08-06 20:07:30 +00:00
"Dec" = > "12"
2017-08-16 22:32:44 +00:00
) ;
2018-08-01 19:20:56 +00:00
# Mappinghash Severity
my % Log2Syslog_Severity = (
"0" = > "Emergency" ,
"1" = > "Alert" ,
"2" = > "Critical" ,
"3" = > "Error" ,
"4" = > "Warning" ,
"5" = > "Notice" ,
"6" = > "Informational" ,
"7" = > "Debug" ,
2018-08-06 20:07:30 +00:00
"Emergency" = > "0" ,
"Alert" = > "1" ,
"Critical" = > "2" ,
"Error" = > "3" ,
"Warning" = > "4" ,
"Notice" = > "5" ,
"Informational" = > "6" ,
"Debug" = > "7"
2018-08-01 19:20:56 +00:00
) ;
# Mappinghash Facility
my % Log2Syslog_Facility = (
"0" = > "kernel" ,
"1" = > "user" ,
"2" = > "mail" ,
"3" = > "system" ,
"4" = > "security" ,
"5" = > "syslog" ,
"6" = > "printer" ,
"7" = > "network" ,
"8" = > "UUCP" ,
"9" = > "clock" ,
"10" = > "security" ,
"11" = > "FTP" ,
"12" = > "NTP" ,
"13" = > "log_audit" ,
"14" = > "log_alert" ,
"15" = > "clock" ,
"16" = > "local0" ,
"17" = > "local1" ,
"18" = > "local2" ,
"19" = > "local3" ,
"20" = > "local4" ,
"21" = > "local5" ,
"22" = > "local6" ,
2018-08-06 20:07:30 +00:00
"23" = > "local7"
2018-08-01 19:20:56 +00:00
) ;
2017-08-17 20:20:38 +00:00
# Längenvorgaben nach RFC3164
my % RFC3164len = ( "TAG" = > 32 , # max. Länge TAG-Feld
"DL" = > 1024 # max. Lange Message insgesamt
) ;
2017-08-22 06:41:25 +00:00
# Längenvorgaben nach RFC5425
2018-08-01 19:20:56 +00:00
my % RFC5425len = ( "DL" = > 8192 , # max. Lange Message insgesamt mit TLS
"HST" = > 255 , # max. Länge Hostname
"ID" = > 48 , # max. Länge APP-NAME bzw. Ident
"PID" = > 128 , # max. Länge Proc-ID
"MID" = > 32 # max. Länge MSGID
2017-08-22 06:41:25 +00:00
) ;
2017-08-17 20:20:38 +00:00
2017-08-27 10:11:05 +00:00
###############################################################################
2017-08-16 22:32:44 +00:00
sub Log2Syslog_Initialize ($) {
my ( $ hash ) = @ _ ;
$ hash - > { DefFn } = "Log2Syslog_Define" ;
$ hash - > { UndefFn } = "Log2Syslog_Undef" ;
$ hash - > { DeleteFn } = "Log2Syslog_Delete" ;
2018-08-08 06:36:04 +00:00
$ hash - > { SetFn } = "Log2Syslog_Set" ;
2018-08-01 19:20:56 +00:00
$ hash - > { GetFn } = "Log2Syslog_Get" ;
2017-08-16 22:32:44 +00:00
$ hash - > { AttrFn } = "Log2Syslog_Attr" ;
2017-08-27 10:11:05 +00:00
$ hash - > { NotifyFn } = "Log2Syslog_eventlog" ;
2018-08-01 19:20:56 +00:00
$ hash - > { ReadFn } = "Log2Syslog_Read" ;
2017-08-16 22:32:44 +00:00
$ hash - > { AttrList } = "addStateEvent:1,0 " .
2018-08-08 06:36:04 +00:00
"disable:1,0,maintenance " .
2017-08-16 22:32:44 +00:00
"addTimestamp:0,1 " .
2018-08-08 20:42:59 +00:00
"contDelimiter " .
2017-08-16 22:32:44 +00:00
"logFormat:BSD,IETF " .
2018-08-13 21:55:35 +00:00
"makeEvent:no,intern,reading " .
2018-08-08 20:42:59 +00:00
"outputFields:sortable-strict,PRIVAL,FAC,SEV,TS,HOST,DATE,TIME,ID,PID,MID,SDFIELD,CONT " .
2018-08-10 12:58:18 +00:00
"parseProfile:BSD,IETF,TPLink-Switch,raw,ParseFn " .
2018-08-05 19:04:41 +00:00
"parseFn:textField-long " .
2018-08-13 21:55:35 +00:00
"respectSeverity:multiple-strict,Emergency,Alert,Critical,Error,Warning,Notice,Informational,Debug " .
2018-08-01 19:20:56 +00:00
"ssldebug:0,1,2,3 " .
2017-08-25 08:28:14 +00:00
"TLS:1,0 " .
"timeout " .
2017-08-27 10:11:05 +00:00
"protocol:UDP,TCP " .
2017-08-25 08:28:14 +00:00
"port " .
2018-08-01 20:30:56 +00:00
"rateCalcRerun " .
$ readingFnAttributes
2017-08-16 22:32:44 +00:00
;
return undef ;
}
2017-08-27 10:11:05 +00:00
###############################################################################
2017-08-16 22:32:44 +00:00
sub Log2Syslog_Define ($@) {
my ( $ hash , $ def ) = @ _ ;
my @ a = split ( "[ \t][ \t]*" , $ def ) ;
2018-08-01 19:20:56 +00:00
my $ name = $ hash - > { NAME } ;
2017-08-16 22:32:44 +00:00
return "Error: Perl module " . $ MissModulSocket . " is missing. Install it on Debian with: sudo apt-get install libio-socket-multicast-perl" if ( $ MissModulSocket ) ;
return "Error: Perl module " . $ MissModulNDom . " is missing." if ( $ MissModulNDom ) ;
2018-08-01 19:20:56 +00:00
# Example Sender: define splunklog Log2Syslog splunk.myds.me ident:Prod event:.* fhem:.*
# Example Collector: define SyslogServer Log2Syslog
2017-08-16 22:32:44 +00:00
delete ( $ hash - > { HELPER } { EVNTLOG } ) ;
delete ( $ hash - > { HELPER } { FHEMLOG } ) ;
2017-08-18 19:51:33 +00:00
delete ( $ hash - > { HELPER } { IDENT } ) ;
2018-08-14 20:44:57 +00:00
$ hash - > { MYFQDN } = hostfqdn ( ) ; # MYFQDN eigener Host (f. IETF)
$ hash - > { MYHOST } = hostname ( ) ; # eigener Host (lt. RFC nur Hostname f. BSD)
2017-08-16 22:32:44 +00:00
2018-08-01 19:20:56 +00:00
if ( int ( @ a ) - 3 < 0 ) {
# Einrichtung Servermode (Collector)
Log3 ( $ name , 3 , "Log2Syslog $name - entering Syslog servermode ..." ) ;
$ hash - > { MODEL } = "Collector" ;
Log2Syslog_initServer ( "$name,global" ) ;
} else {
# Sendermode
$ hash - > { MODEL } = "Sender" ;
Log2Syslog_setidrex ( $ hash , $ a [ 3 ] ) if ( $ a [ 3 ] ) ;
Log2Syslog_setidrex ( $ hash , $ a [ 4 ] ) if ( $ a [ 4 ] ) ;
Log2Syslog_setidrex ( $ hash , $ a [ 5 ] ) if ( $ a [ 5 ] ) ;
eval { "Hallo" =~ m/^$hash->{HELPER}{EVNTLOG}$/ } if ( $ hash - > { HELPER } { EVNTLOG } ) ;
return "Bad regexp: $@" if ( $@ ) ;
eval { "Hallo" =~ m/^$hash->{HELPER}{FHEMLOG}$/ } if ( $ hash - > { HELPER } { FHEMLOG } ) ;
return "Bad regexp: $@" if ( $@ ) ;
return "Bad regexp: starting with *"
if ( ( defined ( $ hash - > { HELPER } { EVNTLOG } ) && $ hash - > { HELPER } { EVNTLOG } =~ m/^\*/ ) || ( defined ( $ hash - > { HELPER } { FHEMLOG } ) && $ hash - > { HELPER } { FHEMLOG } =~ m/^\*/ ) ) ;
# nur Events dieser Devices an NotifyFn weiterleiten, NOTIFYDEV wird gesetzt wenn möglich
notifyRegexpChanged ( $ hash , $ hash - > { HELPER } { EVNTLOG } ) if ( $ hash - > { HELPER } { EVNTLOG } ) ;
2017-08-16 22:32:44 +00:00
2018-08-01 19:20:56 +00:00
$ hash - > { PEERHOST } = $ a [ 2 ] ; # Destination Host (Syslog Server)
}
2017-08-25 08:28:14 +00:00
$ hash - > { SEQNO } = 1 ; # PROCID in IETF, wird kontinuierlich hochgezählt
2017-08-16 22:32:44 +00:00
$ hash - > { VERSION } = $ Log2SyslogVn ;
2017-08-27 10:11:05 +00:00
$ logInform { $ hash - > { NAME } } = "Log2Syslog_fhemlog" ; # Funktion die in hash %loginform für $name eingetragen wird
2017-08-25 08:28:14 +00:00
$ hash - > { HELPER } { SSLVER } = "n.a." ; # Initialisierung
$ hash - > { HELPER } { SSLALGO } = "n.a." ; # Initialisierung
$ hash - > { HELPER } { LTIME } = time ( ) ; # Init Timestmp f. Ratenbestimmung
$ hash - > { HELPER } { OLDSEQNO } = $ hash - > { SEQNO } ; # Init Sequenznummer f. Ratenbestimmung
2018-08-03 08:57:49 +00:00
$ hash - > { HELPER } { OLDSTATE } = "initialized" ;
2017-08-25 08:28:14 +00:00
readingsBeginUpdate ( $ hash ) ;
readingsBulkUpdate ( $ hash , "SSL_Version" , "n.a." ) ;
readingsBulkUpdate ( $ hash , "SSL_Algorithm" , "n.a." ) ;
readingsBulkUpdate ( $ hash , "Transfered_logs_per_minute" , 0 ) ;
2018-08-01 19:20:56 +00:00
readingsBulkUpdate ( $ hash , "state" , "initialized" ) if ( $ hash - > { MODEL } =~ /Sender/ ) ;
2017-08-25 08:28:14 +00:00
readingsEndUpdate ( $ hash , 1 ) ;
2017-08-16 22:32:44 +00:00
2017-08-27 10:11:05 +00:00
Log2Syslog_trate ( $ hash ) ; # regelm. Berechnung Transfer Rate starten
2018-08-01 19:20:56 +00:00
2017-08-16 22:32:44 +00:00
return undef ;
}
2018-08-01 19:20:56 +00:00
#################################################################################################
# Syslog Collector (Server-Mode) initialisieren
# (im Collector Model)
#################################################################################################
sub Log2Syslog_initServer ($) {
my ( $ a ) = @ _ ;
my ( $ name , $ global ) = split ( "," , $ a ) ;
my $ hash = $ defs { $ name } ;
RemoveInternalTimer ( $ hash , "Log2Syslog_initServer" ) ;
return if ( IsDisabled ( $ name ) ) ;
if ( $ init_done != 1 ) {
InternalTimer ( gettimeofday ( ) + 5 , "Log2Syslog_initServer" , "$name,$global" , 0 ) ;
return ;
}
# Inititialisierung FHEM ist fertig -> Attribute geladen
my $ port = AttrVal ( $ name , "TLS" , 0 ) ? AttrVal ( $ name , "port" , 6514 ) : AttrVal ( $ name , "port" , 1514 ) ;
my $ protocol = lc ( AttrVal ( $ name , "protocol" , "udp" ) ) ;
my $ lh = $ global ? ( $ global eq "global" ? undef : $ global ) : ( $ hash - > { IPV6 } ? "::1" : "127.0.0.1" ) ;
Log3 $ hash , 3 , "Log2Syslog $name - Opening socket ..." ;
$ hash - > { SERVERSOCKET } = IO::Socket::INET - > new (
Domain = > ( $ hash - > { IPV6 } ? AF_INET6 ( ) : AF_UNSPEC ) , # Linux bug
LocalHost = > $ lh ,
Proto = > $ protocol ,
LocalPort = > $ port ,
ReuseAddr = > 1
) ;
if ( ! $ hash - > { SERVERSOCKET } ) {
my $ err = "Can't open Syslog Collector at $port: $!" ;
Log3 ( $ hash , 1 , "Log2Syslog $name - $err" ) ;
2018-08-10 06:24:38 +00:00
readingsSingleUpdate ( $ hash , 'state' , $ err , 1 ) ;
2018-08-01 19:20:56 +00:00
return ;
}
$ hash - > { FD } = $ hash - > { SERVERSOCKET } - > fileno ( ) ;
$ hash - > { PORT } = $ hash - > { SERVERSOCKET } - > sockport ( ) ;
$ hash - > { PROTOCOL } = $ protocol ;
$ hash - > { SEQNO } = 1 ; # PROCID wird kontinuierlich pro empfangenen Datensatz hochgezählt
$ hash - > { HELPER } { OLDSEQNO } = $ hash - > { SEQNO } ; # Init Sequenznummer f. Ratenbestimmung
$ hash - > { INTERFACE } = $ lh ? $ lh: "global" ;
2018-08-06 20:07:30 +00:00
Log3 ( $ hash , 3 , "Log2Syslog $name - port $hash->{PORT}/$protocol opened for Syslog Collector on interface \"$hash->{INTERFACE}\"" ) ;
2018-08-10 06:24:38 +00:00
readingsSingleUpdate ( $ hash , "state" , "initialized" , 1 ) ;
2018-08-01 19:20:56 +00:00
delete ( $ readyfnlist { "$name.$port" } ) ;
$ selectlist { "$name.$port" } = $ hash ;
return ;
}
#################################################################################################
# Syslog Collector Daten empfangen
# (im Collector Model)
#################################################################################################
# called from the global loop, when the select for hash->{FD} reports data
sub Log2Syslog_Read ($) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ socket = $ hash - > { SERVERSOCKET } ;
2018-08-05 19:04:41 +00:00
my $ st = ReadingsVal ( $ name , "state" , "active" ) ;
my $ pp = AttrVal ( $ name , "parseProfile" , "IETF" ) ;
2018-08-13 21:55:35 +00:00
my $ mevt = AttrVal ( $ name , "makeEvent" , "intern" ) ; # wie soll Reading/Eventerstellt werden
my $ sevevt = AttrVal ( $ name , "respectSeverity" , "" ) ; # welcher Schweregrad soll berücksichtigt werden (default: alle)
my ( $ err , $ sev , $ data , $ ts , $ phost , $ pl ) ;
2018-08-01 19:20:56 +00:00
2018-08-03 08:57:49 +00:00
return if ( IsDisabled ( $ name ) || $ hash - > { MODEL } !~ /Collector/ ) ;
2018-08-05 19:04:41 +00:00
if ( $ pp =~ /BSD/ ) {
2018-08-01 19:20:56 +00:00
# BSD-Format
unless ( $ socket - > recv ( $ data , $ RFC3164len { DL } ) ) {
# ungültige BSD-Payload
return if ( length ( $ data ) == 0 ) ;
Log2Syslog_Log3slog ( $ hash , 3 , "Log2Syslog $name - received " . length ( $ data ) . " bytes, but a BSD-message has to be 1024 bytes or less." ) ;
Log2Syslog_Log3slog ( $ hash , 3 , "Log2Syslog $name - Seq \"$hash->{SEQNO}\" invalid data: $data" ) ;
$ st = "receive error - see logfile" ;
} else {
# parse Payload
2018-08-13 21:55:35 +00:00
( $ err , $ sev , $ phost , $ ts , $ pl ) = Log2Syslog_parsePayload ( $ hash , $ data ) ;
2018-08-01 19:20:56 +00:00
$ hash - > { SEQNO } + + ;
if ( $ err ) {
$ st = "parse error - see logfile" ;
} else {
2018-08-13 21:55:35 +00:00
return if ( $ sevevt && $ sevevt !~ m/$sev/ ) ; # Message nicht berücksichtigen
2018-08-05 19:04:41 +00:00
$ st = "active" ;
2018-08-06 21:02:42 +00:00
if ( $ mevt =~ /intern/ ) {
# kein Reading, nur Event
$ pl = "$phost: $pl" ;
Log2Syslog_Trigger ( $ hash , $ ts , $ pl ) ;
} elsif ( $ mevt =~ /reading/ ) {
# Reading, Event abhängig von event-on-.*
readingsSingleUpdate ( $ hash , "MSG_$phost" , $ pl , 1 ) ;
} else {
# Reading ohne Event
readingsSingleUpdate ( $ hash , "MSG_$phost" , $ pl , 0 ) ;
}
2018-08-01 19:20:56 +00:00
}
}
2018-08-05 19:04:41 +00:00
} elsif ( $ pp =~ /IETF/ ) {
2018-08-01 19:20:56 +00:00
# IETF-Format
unless ( $ socket - > recv ( $ data , $ RFC5425len { DL } ) ) {
# ungültige IETF-Payload
return if ( length ( $ data ) == 0 ) ;
2018-08-05 19:04:41 +00:00
Log2Syslog_Log3slog ( $ hash , 3 , "Log2Syslog $name - received " . length ( $ data ) . " bytes, but a IETF-message has to be 8192 bytes or less." ) ;
2018-08-01 19:20:56 +00:00
Log2Syslog_Log3slog ( $ hash , 3 , "Log2Syslog $name - Seq \"$hash->{SEQNO}\" invalid data: $data" ) ;
$ st = "receive error - see logfile" ;
} else {
# parse Payload
2018-08-13 21:55:35 +00:00
( $ err , $ sev , $ phost , $ ts , $ pl ) = Log2Syslog_parsePayload ( $ hash , $ data ) ;
2018-08-01 19:20:56 +00:00
$ hash - > { SEQNO } + + ;
if ( $ err ) {
$ st = "parse error - see logfile" ;
} else {
2018-08-13 21:55:35 +00:00
return if ( $ sevevt && $ sevevt !~ m/$sev/ ) ; # Message nicht berücksichtigen
2018-08-05 19:04:41 +00:00
$ st = "active" ;
2018-08-06 21:02:42 +00:00
if ( $ mevt =~ /intern/ ) {
# kein Reading, nur Event
$ pl = "$phost: $pl" ;
Log2Syslog_Trigger ( $ hash , $ ts , $ pl ) ;
} elsif ( $ mevt =~ /reading/ ) {
# Reading, Event abhängig von event-on-.*
readingsSingleUpdate ( $ hash , "MSG_$phost" , $ pl , 1 ) ;
} else {
# Reading ohne Event
readingsSingleUpdate ( $ hash , "MSG_$phost" , $ pl , 0 ) ;
}
2018-08-01 19:20:56 +00:00
}
}
2018-08-05 19:04:41 +00:00
} else {
# raw oder User eigenes Format
$ socket - > recv ( $ data , 8192 ) ;
2018-08-13 21:55:35 +00:00
( $ err , $ sev , $ phost , $ ts , $ pl ) = Log2Syslog_parsePayload ( $ hash , $ data ) ;
2018-08-05 19:04:41 +00:00
$ hash - > { SEQNO } + + ;
if ( $ err ) {
$ st = "parse error - see logfile" ;
} else {
2018-08-13 21:55:35 +00:00
return if ( $ sevevt && $ sevevt !~ m/$sev/ ) ; # Message nicht berücksichtigen
2018-08-05 19:04:41 +00:00
$ st = "active" ;
2018-08-13 21:55:35 +00:00
if ( $ mevt =~ /intern/ ) {
# kein Reading, nur Event
$ pl = "$phost: $pl" ;
Log2Syslog_Trigger ( $ hash , $ ts , $ pl ) ;
} elsif ( $ mevt =~ /reading/ ) {
# Reading, Event abhängig von event-on-.*
readingsSingleUpdate ( $ hash , "MSG_$phost" , $ pl , 1 ) ;
} else {
# Reading ohne Event
readingsSingleUpdate ( $ hash , "MSG_$phost" , $ pl , 0 ) ;
}
2018-08-05 19:04:41 +00:00
}
2018-08-01 19:20:56 +00:00
}
2018-08-03 08:57:49 +00:00
# readingsSingleUpdate($hash, "state", $st, 1) if($st ne OldValue($name));
my $ evt = ( $ st eq $ hash - > { HELPER } { OLDSTATE } ) ? 0 : 1 ;
readingsSingleUpdate ( $ hash , "state" , $ st , $ evt ) ;
$ hash - > { HELPER } { OLDSTATE } = $ st ;
2018-08-01 19:20:56 +00:00
return ;
}
###############################################################################
# Parsen Payload für Syslog-Server
# (im Collector Model)
###############################################################################
sub Log2Syslog_parsePayload ($$) {
my ( $ hash , $ data ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2018-08-05 19:04:41 +00:00
my $ pp = AttrVal ( $ name , "parseProfile" , "IETF" ) ;
my $ severity = "" ;
my $ facility = "" ;
my @ evf = split ( "," , AttrVal ( $ name , "outputFields" , "FAC,SEV,ID,CONT" ) ) ; # auszugebene Felder im Event/Reading
2018-08-09 06:52:31 +00:00
my ( $ Mmm , $ dd , $ delimiter , $ day , $ ietf , $ err , $ pl , $ tail ) ;
2018-08-05 19:04:41 +00:00
# Hash zur Umwandlung Felder in deren Variablen
2018-08-09 06:52:31 +00:00
my ( $ prival , $ ts , $ host , $ date , $ time , $ id , $ pid , $ mid , $ sdfield , $ cont ) ;
my $ fac = "" ;
my $ sev = "" ;
2018-08-05 19:04:41 +00:00
my % fh = ( PRIVAL = > \ $ prival ,
FAC = > \ $ fac ,
SEV = > \ $ sev ,
TS = > \ $ ts ,
HOST = > \ $ host ,
DATE = > \ $ date ,
TIME = > \ $ time ,
ID = > \ $ id ,
PID = > \ $ pid ,
MID = > \ $ mid ,
SDFIELD = > \ $ sdfield ,
CONT = > \ $ cont ,
DATA = > \ $ data
) ;
2018-08-03 08:57:49 +00:00
Log2Syslog_Log3slog ( $ hash , 5 , "Log2Syslog $name - ### new Syslog message Parsing ### " ) ;
# Sender Host / IP-Adresse ermitteln, $phost wird Reading im Event
my ( $ phost , $ paddr ) = Log2Syslog_evalPeer ( $ hash ) ;
$ phost = $ phost ? $ phost: $ paddr ;
2018-08-01 19:20:56 +00:00
2018-08-03 08:57:49 +00:00
Log2Syslog_Log3slog ( $ hash , 5 , "Log2Syslog $name - raw message -> $data" ) ;
2018-08-01 19:20:56 +00:00
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ year , $ wday , $ yday , $ isdst ) = localtime ( time ) ; # Istzeit Ableitung
$ year = $ year + 1900 ;
2018-08-03 15:09:44 +00:00
if ( $ pp =~ /raw/ ) {
Log2Syslog_Log3slog ( $ name , 4 , "$name - $data" ) ;
2018-08-05 19:04:41 +00:00
$ ts = TimeNow ( ) ;
2018-08-06 20:07:30 +00:00
$ pl = $ data ;
2018-08-03 15:09:44 +00:00
2018-08-07 20:54:44 +00:00
} elsif ( $ pp eq "BSD" ) {
2018-08-01 19:20:56 +00:00
# BSD Protokollformat https://tools.ietf.org/html/rfc3164
2018-08-15 06:15:18 +00:00
# Beispiel data "<$prival>$month $day $time $myhost $id: $otp"
2018-08-07 20:54:44 +00:00
$ data =~ /^<(?<prival>\d{1,3})>(?<tail>.*)$/ ;
2018-08-08 06:36:04 +00:00
$ prival = $+ { prival } ; # must
$ tail = $+ { tail } ;
2018-08-07 20:54:44 +00:00
$ tail =~ /^((?<month>\w{3})\s+(?<day>\d{1,2})\s+(?<time>\d{2}:\d{2}:\d{2}))?\s+(?<tail>.*)$/ ;
2018-08-06 20:07:30 +00:00
$ Mmm = $+ { month } ; # should
$ dd = $+ { day } ; # should
$ time = $+ { time } ; # should
2018-08-07 20:54:44 +00:00
$ tail = $+ { tail } ;
if ( $ Mmm && $ dd && $ time ) {
my $ month = $ Log2Syslog_BSDMonth { $ Mmm } ;
$ day = ( length ( $ dd ) == 1 ) ? ( "0" . $ dd ) : $ dd ;
$ ts = "$year-$month-$day $time" ;
}
if ( $ ts ) {
# Annahme: wenn Timestamp gesetzt, wird der Rest der Message ebenfalls dem Standard entsprechen
2018-08-15 06:15:18 +00:00
$ tail =~ /^(?<host>[^\s]*)?\s(?<tail>.*)$/ ;
$ host = $+ { host } ; # should
$ tail = $+ { tail } ;
2018-08-15 13:26:44 +00:00
$ tail =~ /^(?<id>[\w\s]*)?(?<cont>\W.*)$/ ;
2018-08-07 20:54:44 +00:00
$ id = $+ { id } ; # should
2018-08-15 13:26:44 +00:00
if ( $ id ) {
$ id = substr ( $ id , 0 , ( $ RFC3164len { TAG } - 1 ) ) ; # Länge TAG-Feld nach RFC begrenzen
2018-08-15 06:15:18 +00:00
$ cont = $+ { cont } ; # should
} else {
$ cont = $ tail ;
}
2018-08-07 20:54:44 +00:00
} else {
# andernfalls eher kein Standardaufbau
$ cont = $ tail ;
}
2018-08-06 20:07:30 +00:00
if ( ! $ prival ) {
2018-08-03 15:09:44 +00:00
$ err = 1 ;
2018-08-12 18:57:45 +00:00
Log2Syslog_Log3slog ( $ hash , 2 , "Log2Syslog $name - error parse msg -> $data" ) ;
2018-08-03 15:09:44 +00:00
} else {
2018-08-15 13:26:44 +00:00
$ cont =~ s/^(:\s*)(.*)$/$2/ ;
2018-08-06 20:07:30 +00:00
if ( looks_like_number ( $ prival ) ) {
$ facility = int ( $ prival / 8 ) if ( $ prival >= 0 && $ prival <= 191 ) ;
$ severity = $ prival - ( $ facility * 8 ) ;
$ fac = $ Log2Syslog_Facility { $ facility } ;
$ sev = $ Log2Syslog_Severity { $ severity } ;
} else {
$ err = 1 ;
Log2Syslog_Log3slog ( $ hash , 1 , "Log2Syslog $name - error parse msg -> $data" ) ;
}
2018-08-10 10:23:13 +00:00
no warnings 'uninitialized' ;
2018-08-09 06:52:31 +00:00
Log2Syslog_Log3slog ( $ name , 4 , "$name - parsed message -> FAC: $fac, SEV: $sev, MM: $Mmm, Day: $dd, TIME: $time, TS: $ts, HOST: $host, ID: $id, CONT: $cont" ) ;
2018-08-03 15:09:44 +00:00
$ host = "" if ( $ host eq "-" ) ;
2018-08-10 10:23:13 +00:00
use warnings ;
2018-08-03 15:09:44 +00:00
$ phost = $ host ? $ host: $ phost ;
2018-08-05 19:04:41 +00:00
# Payload zusammenstellen für Event/Reading
2018-08-06 20:07:30 +00:00
$ pl = "" ;
2018-08-05 19:04:41 +00:00
my $ i = 0 ;
foreach my $ f ( @ evf ) {
if ( $ { $ fh { $ f } } ) {
$ pl . = " || " if ( $ i ) ;
$ pl . = "$f: " . $ { $ fh { $ f } } ;
$ i + + ;
}
}
2018-08-01 19:20:56 +00:00
}
2018-08-03 15:09:44 +00:00
2018-08-07 20:54:44 +00:00
} elsif ( $ pp eq "IETF" ) {
2018-08-03 15:09:44 +00:00
# IETF Protokollformat https://tools.ietf.org/html/rfc5424
2018-08-12 16:16:31 +00:00
# Beispiel data "<14>1 2018-08-09T21:45:08+02:00 SDS1 Connection - - [synolog@6574 synotype="Connection" luser="apiuser" event="User [apiuser\] logged in from [192.168.2.45\] via [DSM\]."][meta sequenceId="1"] apiuser: User [apiuser] logged in from [192.168.2.45] via [DSM].";
# $data =~ /^<(?<prival>\d{1,3})>(?<ietf>\d+)\s(?<date>\d{4}-\d{2}-\d{2})T(?<time>\d{2}:\d{2}:\d{2})\S*\s(?<host>\S*)\s(?<id>\S*)\s(?<pid>\S*)\s(?<mid>\S*)\s(?<sdfield>(\[.*?(?!\\\]).\]|-))\s(?<cont>.*)$/;
$ data =~ /^<(?<prival>\d{1,3})>(?<ietf>\d{0,2})\s(?<cont>.*)$/ ;
2018-08-06 20:07:30 +00:00
$ prival = $+ { prival } ; # must
2018-08-12 16:16:31 +00:00
$ ietf = $+ { ietf } ; # should
if ( $ prival && $ ietf ) {
# Standard IETF-Syslog incl. VERSION
if ( $ ietf == 1 ) {
$ data =~ /^<(?<prival>\d{1,3})>(?<ietf>\d{0,2})\s?(?<date>\d{4}-\d{2}-\d{2})T(?<time>\d{2}:\d{2}:\d{2})\S*\s(?<host>\S*)\s(?<id>\S*)\s?(?<pid>\S*)\s?(?<mid>\S*)\s?(?<sdfield>(\[.*?(?!\\\]).\]|-))\s(?<cont>.*)$/ ;
$ prival = $+ { prival } ; # must
$ ietf = $+ { ietf } ; # should
$ date = $+ { date } ; # must
$ time = $+ { time } ; # must
$ host = $+ { host } ; # should
$ id = $+ { id } ; # should
$ pid = $+ { pid } ; # should
$ mid = $+ { mid } ; # should
$ sdfield = $+ { sdfield } ; # must
$ cont = $+ { cont } ; # should
} else {
$ err = 1 ;
Log2Syslog_Log3slog ( $ hash , 1 , "Log2Syslog $name - new IETF version detected, inform Log2Syslog Maintainer" ) ;
}
} else {
# IETF-Syslog ohne VERSION
2018-08-12 18:57:45 +00:00
$ data =~ /^<(?<prival>\d{1,3})>(?<date>\d{4}-\d{2}-\d{2})T(?<time>\d{2}:\d{2}:\d{2})\S*\s(?<host>\S*)\s(?<id>\S*)\s?(?<pid>\S*)\s?(?<mid>\S*)\s?(?<sdfield>(\[.*?(?!\\\]).\]|-))?\s(?<cont>.*)$/ ;
2018-08-12 16:16:31 +00:00
$ prival = $+ { prival } ; # must
$ date = $+ { date } ; # must
$ time = $+ { time } ; # must
$ host = $+ { host } ; # should
$ id = $+ { id } ; # should
$ pid = $+ { pid } ; # should
$ mid = $+ { mid } ; # should
2018-08-12 18:57:45 +00:00
$ sdfield = $+ { sdfield } ; # should
2018-08-12 16:16:31 +00:00
$ cont = $+ { cont } ; # should
}
2018-08-06 20:07:30 +00:00
2018-08-12 16:16:31 +00:00
if ( ! $ prival || ! $ date || ! $ time ) {
2018-08-03 15:09:44 +00:00
$ err = 1 ;
2018-08-12 18:57:45 +00:00
Log2Syslog_Log3slog ( $ hash , 2 , "Log2Syslog $name - error parse msg -> $data" ) ;
2018-08-12 16:16:31 +00:00
no warnings 'uninitialized' ;
Log2Syslog_Log3slog ( $ name , 5 , "$name - parsed fields -> PRI: $prival, IETF: $ietf, DATE: $date, TIME: $time, HOST: $host, ID: $id, PID: $pid, MID: $mid, SDFIELD: $sdfield, CONT: $cont" ) ;
use warnings ;
2018-08-03 15:09:44 +00:00
} else {
2018-08-12 16:16:31 +00:00
$ ts = "$date $time" ;
2018-08-01 19:20:56 +00:00
2018-08-06 20:07:30 +00:00
if ( looks_like_number ( $ prival ) ) {
$ facility = int ( $ prival / 8 ) if ( $ prival >= 0 && $ prival <= 191 ) ;
$ severity = $ prival - ( $ facility * 8 ) ;
$ fac = $ Log2Syslog_Facility { $ facility } ;
$ sev = $ Log2Syslog_Severity { $ severity } ;
} else {
$ err = 1 ;
2018-08-12 18:57:45 +00:00
Log2Syslog_Log3slog ( $ hash , 2 , "Log2Syslog $name - error parse msg -> $data" ) ;
2018-08-06 20:07:30 +00:00
}
2018-08-01 19:20:56 +00:00
2018-08-03 15:09:44 +00:00
# Längenbegrenzung nach RFC5424
2018-08-05 19:04:41 +00:00
$ id = substr ( $ id , 0 , ( $ RFC5425len { ID } - 1 ) ) ;
2018-08-03 15:09:44 +00:00
$ pid = substr ( $ pid , 0 , ( $ RFC5425len { PID } - 1 ) ) ;
$ mid = substr ( $ mid , 0 , ( $ RFC5425len { MID } - 1 ) ) ;
$ host = substr ( $ host , 0 , ( $ RFC5425len { HST } - 1 ) ) ;
2018-08-01 19:20:56 +00:00
2018-08-10 12:40:19 +00:00
no warnings 'uninitialized' ;
2018-08-05 19:04:41 +00:00
Log2Syslog_Log3slog ( $ name , 4 , "$name - parsed message -> FAC: $fac, SEV: $sev, TS: $ts, HOST: $host, ID: $id, PID: $pid, MID: $mid, SDFIELD: $sdfield, CONT: $cont" ) ;
2018-08-03 15:09:44 +00:00
$ host = "" if ( $ host eq "-" ) ;
2018-08-10 12:40:19 +00:00
use warnings ;
2018-08-03 15:09:44 +00:00
$ phost = $ host ? $ host: $ phost ;
2018-08-05 19:04:41 +00:00
# Payload zusammenstellen für Event/Reading
2018-08-06 20:07:30 +00:00
$ pl = "" ;
2018-08-05 19:04:41 +00:00
my $ i = 0 ;
foreach my $ f ( @ evf ) {
if ( $ { $ fh { $ f } } ) {
$ pl . = " || " if ( $ i ) ;
$ pl . = "$f: " . $ { $ fh { $ f } } ;
$ i + + ;
}
}
}
2018-08-10 12:40:19 +00:00
2018-08-10 12:58:18 +00:00
} elsif ( $ pp eq "TPLink-Switch" ) {
# Parser für TPLink Switch
2018-08-10 12:40:19 +00:00
# Beispiel data "<131>2018-08-10 09:03:58 10.0.x.y 31890 Login the web by admin on web (10.0.x.y).";
$ data =~ /^<(?<prival>\d{1,3})>(?<date>\d{4}-\d{2}-\d{2})\s(?<time>\d{2}:\d{2}:\d{2})\s(?<host>\S*)\s(?<id>\S*)\s(?<cont>.*)$/ ;
$ prival = $+ { prival } ; # must
$ date = $+ { date } ; # must
$ time = $+ { time } ; # must
$ host = $+ { host } ; # should
$ id = $+ { id } ; # should
$ cont = $+ { cont } ; # should
if ( ! $ prival || ! $ date || ! $ time ) {
$ err = 1 ;
2018-08-12 18:57:45 +00:00
Log2Syslog_Log3slog ( $ hash , 2 , "Log2Syslog $name - error parse msg -> $data" ) ;
2018-08-10 12:40:19 +00:00
} else {
$ ts = "$date $time" ;
if ( looks_like_number ( $ prival ) ) {
$ facility = int ( $ prival / 8 ) if ( $ prival >= 0 && $ prival <= 191 ) ;
$ severity = $ prival - ( $ facility * 8 ) ;
$ fac = $ Log2Syslog_Facility { $ facility } ;
$ sev = $ Log2Syslog_Severity { $ severity } ;
} else {
$ err = 1 ;
2018-08-12 18:57:45 +00:00
Log2Syslog_Log3slog ( $ hash , 2 , "Log2Syslog $name - error parse msg -> $data" ) ;
2018-08-10 12:40:19 +00:00
}
no warnings 'uninitialized' ;
Log2Syslog_Log3slog ( $ name , 4 , "$name - parsed message -> FAC: $fac, SEV: $sev, TS: $ts, HOST: $host, ID: $id, CONT: $cont" ) ;
$ host = "" if ( $ host eq "-" ) ;
use warnings ;
$ phost = $ host ? $ host: $ phost ;
# Payload zusammenstellen für Event/Reading
$ pl = "" ;
my $ i = 0 ;
foreach my $ f ( @ evf ) {
if ( $ { $ fh { $ f } } ) {
$ pl . = " || " if ( $ i ) ;
$ pl . = "$f: " . $ { $ fh { $ f } } ;
$ i + + ;
}
}
}
2018-08-05 19:04:41 +00:00
} elsif ( $ pp eq "ParseFn" ) {
# user spezifisches Parsing
my $ parseFn = AttrVal ( $ name , "parseFn" , "" ) ;
$ ts = TimeNow ( ) ;
if ( $ parseFn =~ m/^\s*(\{.*\})\s*$/s ) {
$ parseFn = $ 1 ;
} else {
$ parseFn = '' ;
}
if ( $ parseFn ne '' ) {
my $ PRIVAL = "" ;
my $ TS = $ ts ;
my $ DATE = "" ;
my $ TIME = "" ;
my $ HOST = "" ;
my $ ID = "" ;
my $ PID = "" ;
my $ MID = "" ;
my $ CONT = "" ;
my $ FAC = "" ;
my $ SEV = "" ;
my $ DATA = $ data ;
my $ SDFIELD = "" ;
eval $ parseFn ;
if ( $@ ) {
2018-08-12 18:57:45 +00:00
Log3 $ name , 2 , "DbLog $name -> error parseFn: $@" ;
2018-08-05 19:04:41 +00:00
$ err = 1 ;
}
$ prival = $ PRIVAL if ( $ PRIVAL =~ /\d{1,3}/ ) ;
$ date = $ DATE if ( $ DATE =~ /^(\d{4})-(\d{2})-(\d{2})$/ ) ;
$ time = $ TIME if ( $ TIME =~ /^(\d{2}):(\d{2}):(\d{2})$/ ) ;
$ ts = ( $ TS =~ /^(\d{4})-(\d{2})-(\d{2})\s(\d{2}):(\d{2}):(\d{2})$/ ) ? $ TS: ( $ date && $ time ) ? "$date $time" : $ ts ;
2018-08-06 20:07:30 +00:00
$ host = $ HOST if ( defined $ HOST ) ;
2018-08-05 19:04:41 +00:00
$ id = $ ID if ( defined $ ID ) ;
$ pid = $ PID if ( defined $ PID ) ;
$ mid = $ MID if ( defined $ MID ) ;
$ cont = $ CONT if ( defined $ CONT ) ;
$ fac = $ FAC if ( defined $ FAC ) ;
$ sev = $ SEV if ( defined $ SEV ) ;
$ sdfield = $ SDFIELD if ( defined $ SDFIELD ) ;
2018-08-06 20:07:30 +00:00
if ( $ prival && looks_like_number ( $ prival ) ) {
$ facility = int ( $ prival / 8 ) if ( $ prival >= 0 && $ prival <= 191 ) ;
2018-08-05 19:04:41 +00:00
$ severity = $ prival - ( $ facility * 8 ) ;
$ fac = $ Log2Syslog_Facility { $ facility } ;
2018-08-06 20:07:30 +00:00
$ sev = $ Log2Syslog_Severity { $ severity } ;
} else {
$ err = 1 ;
2018-08-12 18:57:45 +00:00
Log2Syslog_Log3slog ( $ hash , 2 , "Log2Syslog $name - error parse msg -> $data" ) ;
2018-08-05 19:04:41 +00:00
}
Log2Syslog_Log3slog ( $ name , 4 , "$name - parsed message -> FAC: $fac, SEV: $sev, TS: $ts, HOST: $host, ID: $id, PID: $pid, MID: $mid, CONT: $cont" ) ;
$ phost = $ host ? $ host: $ phost ;
# auszugebene Felder im Event/Reading
my $ ef = "PRIVAL,FAC,SEV,TS,HOST,DATE,TIME,ID,PID,MID,SDFIELD,CONT" ;
@ evf = split ( "," , AttrVal ( $ name , "outputFields" , $ ef ) ) ;
# Payload zusammenstellen für Event/Reading
2018-08-06 20:07:30 +00:00
$ pl = "" ;
2018-08-05 19:04:41 +00:00
my $ i = 0 ;
foreach my $ f ( @ evf ) {
if ( $ { $ fh { $ f } } ) {
$ pl . = " || " if ( $ i ) ;
$ pl . = "$f: " . $ { $ fh { $ f } } ;
$ i + + ;
}
}
} else {
$ err = 1 ;
Log2Syslog_Log3slog ( $ hash , 1 , "Log2Syslog $name - no parseFn defined." ) ;
2018-08-01 19:20:56 +00:00
}
}
if ( AttrVal ( $ name , "TLS" , 0 ) ) {
# wenn Transport Layer Security (TLS) -> Transport Mapping for Syslog https://tools.ietf.org/pdf/rfc5425.pdf
}
2018-08-13 21:55:35 +00:00
return ( $ err , $ sev , $ phost , $ ts , $ pl ) ;
2018-08-01 19:20:56 +00:00
}
#################################################################################################
# Syslog Collector Events erzeugen
# (im Collector Model)
#################################################################################################
sub Log2Syslog_Trigger ($$$) {
2018-08-03 15:09:44 +00:00
my ( $ hash , $ ts , $ pl ) = @ _ ;
2018-08-01 19:20:56 +00:00
my $ name = $ hash - > { NAME } ;
my $ no_replace = 1 ; # Ersetzung von Events durch das Attribut eventMap verhindern
if ( $ hash - > { CHANGED } ) {
push @ { $ hash - > { CHANGED } } , $ pl ;
} else {
$ hash - > { CHANGED } [ 0 ] = $ pl ;
}
if ( $ hash - > { CHANGETIME } ) {
2018-08-03 15:09:44 +00:00
push @ { $ hash - > { CHANGETIME } } , $ ts ;
2018-08-01 19:20:56 +00:00
} else {
2018-08-03 15:09:44 +00:00
$ hash - > { CHANGETIME } [ 0 ] = $ ts ;
2018-08-01 19:20:56 +00:00
}
my $ ret = DoTrigger ( $ name , undef , $ no_replace ) ;
return ;
}
###############################################################################
# Undef Funktion
###############################################################################
2017-08-16 22:32:44 +00:00
sub Log2Syslog_Undef ($$) {
my ( $ hash , $ name ) = @ _ ;
2018-08-01 19:20:56 +00:00
2017-08-27 10:11:05 +00:00
RemoveInternalTimer ( $ hash ) ;
2018-08-01 19:20:56 +00:00
if ( $ hash - > { MODEL } =~ /Collector/ ) {
Log2Syslog_downServer ( $ hash ) ;
}
2017-08-16 22:32:44 +00:00
return undef ;
}
2018-08-01 19:20:56 +00:00
###############################################################################
# Collector-Socket schließen
###############################################################################
sub Log2Syslog_downServer ($) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ port = $ hash - > { PORT } ;
my $ protocol = $ hash - > { PROTOCOL } ;
return if ( ! $ hash - > { SERVERSOCKET } ) ;
Log3 $ hash , 3 , "Log2Syslog $name - Closing socket $protocol/$port ..." ;
my $ ret = $ hash - > { SERVERSOCKET } - > close ( ) ;
Log3 $ hash , 1 , "Log2Syslog $name - Can't close Syslog Collector at port $port: $!" if ( ! $ ret ) ;
delete ( $ hash - > { SERVERSOCKET } ) ;
delete ( $ selectlist { "$name.$port" } ) ;
delete ( $ readyfnlist { "$name.$port" } ) ;
delete ( $ hash - > { FD } ) ;
return ;
}
###############################################################################
# Delete Funktion
###############################################################################
2017-08-16 22:32:44 +00:00
sub Log2Syslog_Delete ($$) {
my ( $ hash , $ arg ) = @ _ ;
delete $ logInform { $ hash - > { NAME } } ;
return undef ;
}
2018-08-08 06:36:04 +00:00
###############################################################################
# Set
###############################################################################
sub Log2Syslog_Set ($@) {
my ( $ hash , @ a ) = @ _ ;
return "\"set X\" needs at least an argument" if ( @ a < 2 ) ;
my $ name = $ a [ 0 ] ;
my $ opt = $ a [ 1 ] ;
my $ prop = $ a [ 2 ] ;
my $ setlist = "Unknown argument $opt, choose one of " .
"sendTestMessage "
;
return if ( AttrVal ( $ name , "disable" , "" ) eq "1" || $ hash - > { MODEL } !~ /Sender/ ) ;
if ( $ opt =~ /sendTestMessage/ ) {
my $ own ;
if ( $ prop ) {
shift @ a ;
shift @ a ;
$ own = join ( " " , @ a ) ;
}
Log2Syslog_sendTestMsg ( $ hash , $ own ) ;
} else {
return "$setlist" ;
}
return undef ;
}
2017-08-27 10:11:05 +00:00
###############################################################################
2018-08-01 19:20:56 +00:00
# Get
###############################################################################
sub Log2Syslog_Get ($@) {
my ( $ hash , @ a ) = @ _ ;
return "\"get X\" needs at least an argument" if ( @ a < 2 ) ;
my $ name = $ a [ 0 ] ;
my $ opt = $ a [ 1 ] ;
my $ prop = $ a [ 2 ] ;
my $ getlist = "Unknown argument $opt, choose one of " .
"certinfo:noArg "
;
2018-08-08 20:42:59 +00:00
return if ( AttrVal ( $ name , "disable" , "" ) eq "1" ) ;
2018-08-01 19:20:56 +00:00
my ( $ sock , $ cert , @ certs ) ;
if ( $ opt =~ /certinfo/ ) {
if ( ReadingsVal ( $ name , "SSL_Version" , "n.a." ) ne "n.a." ) {
2018-08-08 20:51:50 +00:00
$ sock = Log2Syslog_opensock ( $ hash ) ;
2018-08-01 19:20:56 +00:00
if ( defined ( $ sock ) ) {
$ cert = $ sock - > dump_peer_certificate ( ) ;
Log2Syslog_closesock ( $ hash , $ sock ) ;
}
}
return $ cert if ( $ cert ) ;
return "no SSL session has been created" ;
} else {
return "$getlist" ;
}
return undef ;
}
###############################################################################
sub Log2Syslog_Attr ($$$$) {
2017-08-16 22:32:44 +00:00
my ( $ cmd , $ name , $ aName , $ aVal ) = @ _ ;
my $ hash = $ defs { $ name } ;
my $ do ;
# $cmd can be "del" or "set"
# $name is device name
# aName and aVal are Attribute name and value
2018-08-05 19:04:41 +00:00
2018-08-13 21:55:35 +00:00
if ( $ cmd eq "set" && $ hash - > { MODEL } !~ /Collector/ && $ aName =~ /parseProfile|parseFn|outputFields|makeEvent/ ) {
2018-08-05 19:04:41 +00:00
return "\"$aName\" is only valid for model \"Collector\"" ;
}
2018-08-13 21:55:35 +00:00
if ( $ cmd eq "set" && $ hash - > { MODEL } =~ /Collector/ && $ aName =~ /addTimestamp|contDelimiter|addStateEvent|protocol|logFormat|timeout|TLS/ ) {
2018-08-05 19:04:41 +00:00
return "\"$aName\" is only valid for model \"Sender\"" ;
}
2017-08-16 22:32:44 +00:00
if ( $ aName eq "disable" ) {
if ( $ cmd eq "set" ) {
2018-08-08 06:36:04 +00:00
return "Mode \"$aVal\" is only valid for model \"Sender\"" if ( $ aVal eq "maintenance" && $ hash - > { MODEL } !~ /Sender/ ) ;
2018-08-05 19:04:41 +00:00
$ do = $ aVal ? 1 : 0 ;
2017-08-16 22:32:44 +00:00
}
$ do = 0 if ( $ cmd eq "del" ) ;
2018-08-08 20:42:59 +00:00
my $ val = ( $ do && $ aVal =~ /maintenance/ ) ? "maintenance" : ( $ do && $ aVal == 1 ) ? "disabled" : "active" ;
2017-08-16 22:32:44 +00:00
readingsSingleUpdate ( $ hash , "state" , $ val , 1 ) ;
}
2017-08-25 08:28:14 +00:00
if ( $ aName eq "TLS" ) {
if ( $ cmd eq "set" ) {
$ do = ( $ aVal ) ? 1 : 0 ;
}
$ do = 0 if ( $ cmd eq "del" ) ;
if ( $ do == 0 ) {
$ hash - > { HELPER } { SSLVER } = "n.a." ;
$ hash - > { HELPER } { SSLALGO } = "n.a." ;
readingsSingleUpdate ( $ hash , "SSL_Version" , "n.a." , 1 ) ;
readingsSingleUpdate ( $ hash , "SSL_Algorithm" , "n.a." , 1 ) ;
}
}
2018-08-01 19:20:56 +00:00
2018-08-05 19:04:41 +00:00
if ( $ aName =~ /rateCalcRerun/ ) {
unless ( $ aVal =~ /^[0-9]+$/ ) { return "Value of $aName is not valid. Use only figures 0-9 without decimal places !" ; }
$ _ [ 3 ] = 60 if ( $ aVal < 60 ) ;
2018-08-01 19:20:56 +00:00
RemoveInternalTimer ( $ hash , "Log2Syslog_trate" ) ;
InternalTimer ( gettimeofday ( ) + 5 , "Log2Syslog_trate" , $ hash , 0 ) ;
}
2017-08-25 08:28:14 +00:00
2018-08-05 19:04:41 +00:00
if ( $ cmd eq "set" && $ aName =~ /port|timeout/ ) {
2017-08-16 22:32:44 +00:00
if ( $ aVal !~ m/^\d+$/ ) { return " The Value of \"$aName\" is not valid. Use only figures !" ; }
2018-08-05 19:04:41 +00:00
if ( $ aName =~ /port/ && $ hash - > { MODEL } =~ /Collector/ && $ init_done ) {
2018-08-01 19:20:56 +00:00
return "$aName \"$aVal\" is not valid because privileged ports are only usable by super users. Use a port grater than 1023." if ( $ aVal < 1024 ) ;
Log2Syslog_downServer ( $ hash ) ;
RemoveInternalTimer ( $ hash , "Log2Syslog_initServer" ) ;
InternalTimer ( gettimeofday ( ) + 1.5 , "Log2Syslog_initServer" , "$name,global" , 0 ) ;
}
}
2018-08-05 19:04:41 +00:00
if ( $ cmd eq "set" && $ aName =~ /parseFn/ ) {
$ _ [ 3 ] = "{$aVal}" if ( $ aVal !~ m/^\{.*\}$/s ) ;
$ aVal = $ _ [ 3 ] ;
my % specials = (
"%DATA" = > "1" ,
"%PRIVAL" = > "1" ,
"%TS" = > "1" ,
"%DATE" = > "1" ,
"%TIME" = > "1" ,
"%HOST" = > "1" ,
"%ID" = > "1" ,
"%PID" = > "1" ,
"%MID" = > "1" ,
"%CONT" = > "1" ,
"%FAC" = > "1" ,
"%SDFIELD" = > "1" ,
"%SEV" = > "1"
) ;
my $ err = perlSyntaxCheck ( $ aVal , % specials ) ;
return $ err if ( $ err ) ;
2018-08-01 19:20:56 +00:00
}
2018-08-05 19:04:41 +00:00
if ( $ cmd eq "set" && $ aName =~ /parseProfile/ && $ aVal =~ /ParseFn/ ) {
return "You have to define a parse-function via attribute \"parseFn\" first !" if ( ! AttrVal ( $ name , "parseFn" , "" ) ) ;
2017-08-16 22:32:44 +00:00
}
2018-08-05 19:04:41 +00:00
if ( $ cmd eq "del" && $ aName =~ /parseFn/ && AttrVal ( $ name , "parseProfile" , "" ) eq "ParseFn" ) {
return "You use a parse-function via attribute \"parseProfile\". Please change/delete attribute \"parseProfile\" first !" ;
}
2018-08-13 21:55:35 +00:00
if ( $ aName =~ /makeEvent/ ) {
2018-08-08 20:42:59 +00:00
if ( $ aVal =~ /intern/ || $ cmd eq "del" ) {
foreach my $ reading ( grep { /MSG_/ } keys % { $ defs { $ name } { READINGS } } ) {
readingsDelete ( $ defs { $ name } , $ reading ) ;
}
2018-08-06 21:02:42 +00:00
}
}
2018-08-05 19:04:41 +00:00
return ;
2017-08-16 22:32:44 +00:00
}
#################################################################################
# Eventlogging
#################################################################################
2017-08-27 10:11:05 +00:00
sub Log2Syslog_eventlog ($$) {
2017-08-16 22:32:44 +00:00
# $hash is my entry, $dev is the entry of the changed device
my ( $ hash , $ dev ) = @ _ ;
2018-08-08 20:42:59 +00:00
my $ name = $ hash - > { NAME } ;
my $ rex = $ hash - > { HELPER } { EVNTLOG } ;
my $ st = ReadingsVal ( $ name , "state" , "active" ) ;
2018-08-13 21:55:35 +00:00
my $ sendsev = AttrVal ( $ name , "respectSeverity" , "" ) ; # Nachrichten welcher Schweregrade sollen gesendet werden
2018-08-08 20:42:59 +00:00
my ( $ prival , $ sock , $ data , $ pid , $ sevAstxt ) ;
2017-08-16 22:32:44 +00:00
2018-08-01 19:20:56 +00:00
return if ( IsDisabled ( $ name ) || ! $ rex || $ hash - > { MODEL } !~ /Sender/ ) ;
2017-08-16 22:32:44 +00:00
my $ events = deviceEvents ( $ dev , AttrVal ( $ name , "addStateEvent" , 0 ) ) ;
return if ( ! $ events ) ;
my $ n = $ dev - > { NAME } ;
my $ max = int ( @ { $ events } ) ;
my $ tn = $ dev - > { NTFY_TRIGGERTIME } ;
my $ ct = $ dev - > { CHANGETIME } ;
2018-08-08 20:51:50 +00:00
$ sock = Log2Syslog_opensock ( $ hash ) ;
2017-08-22 06:41:25 +00:00
2017-08-25 08:28:14 +00:00
if ( defined ( $ sock ) ) {
2017-08-22 06:41:25 +00:00
for ( my $ i = 0 ; $ i < $ max ; $ i + + ) {
my $ txt = $ events - > [ $ i ] ;
$ txt = "" if ( ! defined ( $ txt ) ) ;
2017-08-27 10:11:05 +00:00
$ txt = Log2Syslog_charfilter ( $ hash , $ txt ) ;
2017-08-17 20:20:38 +00:00
2017-08-22 06:41:25 +00:00
my $ tim = ( ( $ ct && $ ct - > [ $ i ] ) ? $ ct - > [ $ i ] : $ tn ) ;
my ( $ date , $ time ) = split ( " " , $ tim ) ;
2017-08-16 22:32:44 +00:00
2017-08-25 08:28:14 +00:00
if ( $ n =~ m/^$rex$/ || "$n:$txt" =~ m/^$rex$/ || "$tim:$n:$txt" =~ m/^$rex$/ ) {
2018-08-08 20:42:59 +00:00
my $ otp = "$n $txt" ;
$ otp = "$tim $otp" if AttrVal ( $ name , 'addTimestamp' , 0 ) ;
( $ prival , $ sevAstxt ) = Log2Syslog_setprival ( $ txt ) ;
if ( $ sendsev && $ sendsev !~ m/$sevAstxt/ ) {
2018-08-13 21:55:35 +00:00
# nicht senden wenn Severity nicht in "respectSeverity" enthalten
Log2Syslog_Log3slog ( $ name , 5 , "$name - Warning - Payload NOT sent due to Message Severity not in attribute \"respectSeverity\"\n" ) ;
2018-08-08 20:42:59 +00:00
next ;
}
2017-08-25 08:28:14 +00:00
2017-08-27 10:11:05 +00:00
( $ data , $ pid ) = Log2Syslog_setpayload ( $ hash , $ prival , $ date , $ time , $ otp , "event" ) ;
2017-08-25 08:28:14 +00:00
next if ( ! $ data ) ;
my $ ret = syswrite $ sock , $ data . "\n" ;
2017-08-27 10:11:05 +00:00
if ( $ ret && $ ret > 0 ) {
Log2Syslog_Log3slog ( $ name , 4 , "$name - Payload sequence $pid sent\n" ) ;
2017-08-22 06:41:25 +00:00
} else {
2017-08-25 08:28:14 +00:00
my $ err = $! ;
2017-08-27 10:11:05 +00:00
Log2Syslog_Log3slog ( $ name , 4 , "$name - Warning - Payload sequence $pid NOT sent: $err\n" ) ;
2018-08-08 20:42:59 +00:00
$ st = "write error: $err" ;
2017-08-22 06:41:25 +00:00
}
}
2018-08-03 08:57:49 +00:00
}
2017-08-27 10:11:05 +00:00
Log2Syslog_closesock ( $ hash , $ sock ) ;
2018-08-03 08:57:49 +00:00
}
2018-08-08 20:42:59 +00:00
my $ evt = ( $ st eq $ hash - > { HELPER } { OLDSTATE } ) ? 0 : 1 ;
readingsSingleUpdate ( $ hash , "state" , $ st , $ evt ) ;
$ hash - > { HELPER } { OLDSTATE } = $ st ;
2017-08-16 22:32:44 +00:00
return "" ;
}
#################################################################################
# FHEM system logging
#################################################################################
2017-08-27 10:11:05 +00:00
sub Log2Syslog_fhemlog ($$) {
2017-08-16 22:32:44 +00:00
my ( $ name , $ raw ) = @ _ ;
2018-08-08 20:42:59 +00:00
my $ hash = $ defs { $ name } ;
my $ rex = $ hash - > { HELPER } { FHEMLOG } ;
my $ st = ReadingsVal ( $ name , "state" , "active" ) ;
2018-08-13 21:55:35 +00:00
my $ sendsev = AttrVal ( $ name , "respectSeverity" , "" ) ; # Nachrichten welcher Schweregrade sollen gesendet werden
2018-08-08 20:42:59 +00:00
my ( $ prival , $ sock , $ err , $ ret , $ data , $ pid , $ sevAstxt ) ;
2017-08-16 22:32:44 +00:00
2018-08-01 19:20:56 +00:00
return if ( IsDisabled ( $ name ) || ! $ rex || $ hash - > { MODEL } !~ /Sender/ ) ;
2017-08-16 22:32:44 +00:00
2017-08-18 19:51:33 +00:00
my ( $ date , $ time , $ vbose , undef , $ txt ) = split ( " " , $ raw , 5 ) ;
2017-08-27 10:11:05 +00:00
$ txt = Log2Syslog_charfilter ( $ hash , $ txt ) ;
2017-08-16 22:32:44 +00:00
$ date =~ s/\./-/g ;
my $ tim = $ date . " " . $ time ;
2017-08-17 20:20:38 +00:00
2017-08-25 08:28:14 +00:00
if ( $ txt =~ m/^$rex$/ || "$vbose: $txt" =~ m/^$rex$/ ) {
2018-08-08 20:42:59 +00:00
my $ otp = "$vbose: $txt" ;
$ otp = "$tim $otp" if AttrVal ( $ name , 'addTimestamp' , 0 ) ;
( $ prival , $ sevAstxt ) = Log2Syslog_setprival ( $ txt , $ vbose ) ;
if ( $ sendsev && $ sendsev !~ m/$sevAstxt/ ) {
2018-08-13 21:55:35 +00:00
# nicht senden wenn Severity nicht in "respectSeverity" enthalten
Log2Syslog_Log3slog ( $ name , 5 , "$name - Warning - Payload NOT sent due to Message Severity not in attribute \"respectSeverity\"\n" ) ;
2018-08-08 20:42:59 +00:00
return ;
}
2017-08-25 08:28:14 +00:00
2017-08-27 10:11:05 +00:00
( $ data , $ pid ) = Log2Syslog_setpayload ( $ hash , $ prival , $ date , $ time , $ otp , "fhem" ) ;
2017-08-25 08:28:14 +00:00
return if ( ! $ data ) ;
2017-08-20 08:19:32 +00:00
2018-08-08 20:51:50 +00:00
$ sock = Log2Syslog_opensock ( $ hash ) ;
2017-08-22 06:41:25 +00:00
2017-08-25 08:28:14 +00:00
if ( defined ( $ sock ) ) {
$ ret = syswrite $ sock , $ data . "\n" if ( $ data ) ;
2017-08-27 10:11:05 +00:00
if ( $ ret && $ ret > 0 ) {
Log2Syslog_Log3slog ( $ name , 4 , "$name - Payload sequence $pid sent\n" ) ;
2017-08-22 06:41:25 +00:00
} else {
2017-08-25 08:28:14 +00:00
my $ err = $! ;
2017-08-27 10:11:05 +00:00
Log2Syslog_Log3slog ( $ name , 4 , "$name - Warning - Payload sequence $pid NOT sent: $err\n" ) ;
2018-08-08 20:42:59 +00:00
$ st = "write error: $err" ;
2018-08-03 08:57:49 +00:00
}
2017-08-27 10:11:05 +00:00
Log2Syslog_closesock ( $ hash , $ sock ) ;
2017-08-17 06:52:49 +00:00
}
2017-08-16 22:32:44 +00:00
}
2018-08-08 20:42:59 +00:00
my $ evt = ( $ st eq $ hash - > { HELPER } { OLDSTATE } ) ? 0 : 1 ;
readingsSingleUpdate ( $ hash , "state" , $ st , $ evt ) ;
$ hash - > { HELPER } { OLDSTATE } = $ st ;
2017-08-22 06:41:25 +00:00
2017-08-17 20:20:38 +00:00
return ;
2017-08-17 06:52:49 +00:00
}
2018-08-08 06:36:04 +00:00
#################################################################################
# Test Message senden
#################################################################################
sub Log2Syslog_sendTestMsg ($$) {
my ( $ hash , $ own ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2018-08-08 20:42:59 +00:00
my $ st = ReadingsVal ( $ name , "state" , "active" ) ;
2018-08-08 06:36:04 +00:00
my ( $ prival , $ ts , $ tim , $ date , $ time , $ sock , $ err , $ ret , $ data , $ pid , $ otp ) ;
if ( $ own ) {
# eigene Testmessage ohne Formatanpassung raw senden
$ data = $ own ;
} else {
$ ts = TimeNow ( ) ;
( $ date , $ time ) = split ( " " , $ ts ) ;
$ date =~ s/\./-/g ;
$ tim = $ date . " " . $ time ;
$ otp = "Test message from FHEM Syslog Client from ($hash->{MYHOST})" ;
$ otp = "$tim $otp" if AttrVal ( $ name , 'addTimestamp' , 0 ) ;
$ prival = "14" ;
( $ data , $ pid ) = Log2Syslog_setpayload ( $ hash , $ prival , $ date , $ time , $ otp , "fhem" ) ;
return if ( ! $ data ) ;
}
2018-08-08 20:51:50 +00:00
$ sock = Log2Syslog_opensock ( $ hash ) ;
2018-08-08 06:36:04 +00:00
if ( defined ( $ sock ) ) {
$ ret = syswrite $ sock , $ data . "\n" if ( $ data ) ;
if ( $ ret && $ ret > 0 ) {
Log2Syslog_Log3slog ( $ name , 4 , "$name - Payload sequence $pid sent\n" ) ;
} else {
my $ err = $! ;
Log2Syslog_Log3slog ( $ name , 4 , "$name - Warning - Payload sequence $pid NOT sent: $err\n" ) ;
2018-08-08 20:42:59 +00:00
$ st = "write error: $err" ;
2018-08-08 06:36:04 +00:00
}
Log2Syslog_closesock ( $ hash , $ sock ) ;
}
2018-08-08 20:42:59 +00:00
my $ evt = ( $ st eq $ hash - > { HELPER } { OLDSTATE } ) ? 0 : 1 ;
readingsSingleUpdate ( $ hash , "state" , $ st , $ evt ) ;
$ hash - > { HELPER } { OLDSTATE } = $ st ;
2018-08-08 06:36:04 +00:00
return ;
}
2017-08-17 06:52:49 +00:00
###############################################################################
2017-08-18 19:51:33 +00:00
# Helper für ident & Regex setzen
###############################################################################
2017-08-27 10:11:05 +00:00
sub Log2Syslog_setidrex ($$) {
2017-08-18 19:51:33 +00:00
my ( $ hash , $ a ) = @ _ ;
$ hash - > { HELPER } { EVNTLOG } = ( split ( "event:" , $ a ) ) [ 1 ] if ( lc ( $ a ) =~ m/^event:.*/ ) ;
$ hash - > { HELPER } { FHEMLOG } = ( split ( "fhem:" , $ a ) ) [ 1 ] if ( lc ( $ a ) =~ m/^fhem:.*/ ) ;
$ hash - > { HELPER } { IDENT } = ( split ( "ident:" , $ a ) ) [ 1 ] if ( lc ( $ a ) =~ m/^ident:.*/ ) ;
return ;
}
###############################################################################
# Zeichencodierung für Payload filtern
###############################################################################
2017-08-27 10:11:05 +00:00
sub Log2Syslog_charfilter ($$) {
2017-08-18 19:51:33 +00:00
my ( $ hash , $ txt ) = @ _ ;
my $ name = $ hash - > { NAME } ;
# nur erwünschte Zeichen in payload, ASCII %d32-126
$ txt =~ s/ß/ss/g ;
$ txt =~ s/ä/ae/g ;
$ txt =~ s/ö/oe/g ;
$ txt =~ s/ü/ue/g ;
2017-08-22 06:41:25 +00:00
$ txt =~ s/Ä/Ae/g ;
$ txt =~ s/Ö/Oe/g ;
$ txt =~ s/Ü/Ue/g ;
$ txt =~ s/€/EUR/g ;
2017-08-18 19:51:33 +00:00
$ txt =~ tr / A-Za-z0-9!"#$%&'()*+,-.\/:;<=>?@[\]^_`{|}~/ / cd ;
return ( $ txt ) ;
}
###############################################################################
# erstelle Socket
2017-08-17 06:52:49 +00:00
###############################################################################
2018-08-08 20:51:50 +00:00
sub Log2Syslog_opensock ($) {
2017-08-27 10:11:05 +00:00
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ host = $ hash - > { PEERHOST } ;
my $ port = AttrVal ( $ name , "TLS" , 0 ) ? AttrVal ( $ name , "port" , 6514 ) : AttrVal ( $ name , "port" , 514 ) ;
my $ protocol = lc ( AttrVal ( $ name , "protocol" , "udp" ) ) ;
2018-08-05 19:04:41 +00:00
my $ st = ReadingsVal ( $ name , "state" , "active" ) ;
2017-08-27 10:11:05 +00:00
my $ timeout = AttrVal ( $ name , "timeout" , 0.5 ) ;
2018-08-01 19:20:56 +00:00
my $ ssldbg = AttrVal ( $ name , "ssldebug" , 0 ) ;
2017-08-25 08:28:14 +00:00
my ( $ sock , $ lo , $ sslver , $ sslalgo ) ;
2018-08-01 19:20:56 +00:00
return undef if ( $ init_done != 1 || $ hash - > { MODEL } !~ /Sender/ ) ;
2017-08-25 08:28:14 +00:00
if ( AttrVal ( $ name , "TLS" , 0 ) ) {
# TLS gesicherte Verbindung
# TLS Transport nach RFC5425 https://tools.ietf.org/pdf/rfc5425.pdf
2017-08-27 10:11:05 +00:00
$ attr { $ name } { protocol } = "TCP" if ( AttrVal ( $ name , "protocol" , "UDP" ) ne "TCP" ) ;
2017-08-25 08:28:14 +00:00
$ sslver = "n.a." ;
$ sslalgo = "n.a." ;
eval "use IO::Socket::SSL" ;
if ( $@ ) {
$ st = "$@" ;
} else {
$ sock = IO::Socket::INET - > new ( PeerHost = > $ host , PeerPort = > $ port , Proto = > 'tcp' , Blocking = > 0 ) ;
if ( ! $ sock ) {
2018-08-01 19:20:56 +00:00
$ st = "unable open socket for $host, $protocol, $port: $!" ;
2017-08-25 08:28:14 +00:00
} else {
$ sock - > blocking ( 1 ) ;
2018-08-01 19:20:56 +00:00
$ IO:: Socket:: SSL:: DEBUG = $ ssldbg ;
2017-08-25 08:28:14 +00:00
eval { IO::Socket::SSL - > start_SSL ( $ sock ,
2018-08-01 19:20:56 +00:00
SSL_verify_mode = > 0 ,
SSL_version = > "TLSv1_2:!TLSv1_1:!SSLv3:!SSLv23:!SSLv2" ,
2017-08-25 08:28:14 +00:00
SSL_hostname = > $ host ,
SSL_veriycn_scheme = > "rfc5425" ,
SSL_veriycn_publicsuffix = > '' ,
Timeout = > $ timeout
) || undef $ sock ; } ;
2018-08-01 19:20:56 +00:00
$ IO:: Socket:: SSL:: DEBUG = 0 ;
if ( $@ ) {
$ st = "SSL error: $@" ;
undef $ sock ;
} elsif ( ! $ sock ) {
2017-08-25 08:28:14 +00:00
$ st = "SSL error: " . IO::Socket::SSL:: errstr ( ) ;
2018-08-01 19:20:56 +00:00
undef $ sock ;
2017-08-25 08:28:14 +00:00
} else {
$ sslver = $ sock - > get_sslversion ( ) ;
$ sslalgo = $ sock - > get_fingerprint ( ) ;
$ sslalgo = ( split ( "\\\$" , $ sslalgo ) ) [ 0 ] ;
2017-08-27 10:11:05 +00:00
$ lo = "Socket opened for Host: $host, Protocol: $protocol, Port: $port, TLS: 0" ;
2018-08-01 19:20:56 +00:00
$ st = "active" ;
2017-08-25 08:28:14 +00:00
}
}
}
2017-08-22 06:41:25 +00:00
} else {
2017-08-25 08:28:14 +00:00
# erstellt ungesicherte Socket Verbindung
$ sslver = "n.a." ;
$ sslalgo = "n.a." ;
2017-08-27 10:11:05 +00:00
$ sock = new IO::Socket:: INET ( PeerHost = > $ host , PeerPort = > $ port , Proto = > $ protocol , Timeout = > $ timeout ) ;
2017-08-25 08:28:14 +00:00
if ( ! $ sock ) {
undef $ sock ;
2018-08-01 19:20:56 +00:00
$ st = "unable open socket for $host, $protocol, $port: $!" ;
2017-08-25 08:28:14 +00:00
} else {
$ sock - > blocking ( 0 ) ;
2018-08-05 19:04:41 +00:00
$ st = "active" ;
2017-08-25 08:28:14 +00:00
# Logausgabe (nur in das fhem Logfile !)
2017-08-27 10:11:05 +00:00
$ lo = "Socket opened for Host: $host, Protocol: $protocol, Port: $port, TLS: 0" ;
2017-08-25 08:28:14 +00:00
}
}
2018-08-03 08:57:49 +00:00
my $ evt = ( $ st eq $ hash - > { HELPER } { OLDSTATE } ) ? 0 : 1 ;
readingsSingleUpdate ( $ hash , "state" , $ st , $ evt ) ;
$ hash - > { HELPER } { OLDSTATE } = $ st ;
2017-08-25 08:28:14 +00:00
if ( $ sslver ne $ hash - > { HELPER } { SSLVER } ) {
readingsSingleUpdate ( $ hash , "SSL_Version" , $ sslver , 1 ) ;
$ hash - > { HELPER } { SSLVER } = $ sslver ;
2017-08-22 06:41:25 +00:00
}
2018-08-01 19:20:56 +00:00
2017-08-25 08:28:14 +00:00
if ( $ sslalgo ne $ hash - > { HELPER } { SSLALGO } ) {
readingsSingleUpdate ( $ hash , "SSL_Algorithm" , $ sslalgo , 1 ) ;
$ hash - > { HELPER } { SSLALGO } = $ sslalgo ;
}
2017-08-27 10:11:05 +00:00
Log2Syslog_Log3slog ( $ name , 5 , "$name - $lo" ) if ( $ lo ) ;
2017-08-20 08:19:32 +00:00
2017-08-17 06:52:49 +00:00
return ( $ sock ) ;
2017-08-16 22:32:44 +00:00
}
2017-08-27 10:11:05 +00:00
###############################################################################
# Socket schließen
###############################################################################
sub Log2Syslog_closesock ($$) {
my ( $ hash , $ sock ) = @ _ ;
shutdown ( $ sock , 1 ) ;
if ( AttrVal ( $ hash - > { NAME } , "TLS" , 0 ) ) {
$ sock - > close ( SSL_no_shutdown = > 1 ) ;
} else {
$ sock - > close ( ) ;
}
return ;
}
2017-08-16 22:32:44 +00:00
###############################################################################
# set PRIVAL (severity & facility)
###############################################################################
2017-08-27 10:11:05 +00:00
sub Log2Syslog_setprival ($;$$) {
2017-08-18 19:51:33 +00:00
my ( $ txt , $ vbose ) = @ _ ;
2018-08-08 20:42:59 +00:00
my ( $ prival , $ sevAstxt ) ;
2017-08-16 22:32:44 +00:00
# Priority = (facility * 8) + severity
2017-08-19 15:09:53 +00:00
# https://tools.ietf.org/pdf/rfc5424.pdf
2017-08-16 22:32:44 +00:00
# determine facility
2018-08-01 19:20:56 +00:00
my $ fac = 5 ; # facility by syslogd
2017-08-16 22:32:44 +00:00
# calculate severity
# mapping verbose level to severity
# 0: Critical -> 2
# 1: Error -> 3
# 2: Warning -> 4
# 3: Notice -> 5
# 4: Informational -> 6
# 5: Debug -> 7
my $ sv = 5 ; # notice (default)
if ( $ vbose ) {
# map verbose to severity
$ sv = 2 if ( $ vbose == 0 ) ;
$ sv = 3 if ( $ vbose == 1 ) ;
$ sv = 4 if ( $ vbose == 2 ) ;
$ sv = 5 if ( $ vbose == 3 ) ;
$ sv = 6 if ( $ vbose == 4 ) ;
$ sv = 7 if ( $ vbose == 5 ) ;
}
2017-08-18 19:51:33 +00:00
$ sv = 3 if ( lc ( $ txt ) =~ m/error/ ) ; # error condition
$ sv = 4 if ( lc ( $ txt ) =~ m/warning/ ) ; # warning conditions
2017-08-16 22:32:44 +00:00
2018-08-08 20:42:59 +00:00
$ prival = ( $ fac * 8 ) + $ sv ;
$ sevAstxt = $ Log2Syslog_Severity { $ sv } ;
2017-08-16 22:32:44 +00:00
2018-08-08 20:42:59 +00:00
return ( $ prival , $ sevAstxt ) ;
2017-08-16 22:32:44 +00:00
}
###############################################################################
2017-08-18 19:51:33 +00:00
# erstellen Payload für Syslog
2017-08-16 22:32:44 +00:00
###############################################################################
2017-08-27 10:11:05 +00:00
sub Log2Syslog_setpayload ($$$$$$) {
2017-08-18 19:51:33 +00:00
my ( $ hash , $ prival , $ date , $ time , $ otp , $ lt ) = @ _ ;
2017-08-16 22:32:44 +00:00
my $ name = $ hash - > { NAME } ;
2017-08-18 19:51:33 +00:00
my $ ident = ( $ hash - > { HELPER } { IDENT } ? $ hash - > { HELPER } { IDENT } : $ name ) . "_" . $ lt ;
2017-08-16 22:32:44 +00:00
my $ myhost = $ hash - > { MYHOST } ? $ hash - > { MYHOST } : "0.0.0.0" ;
2018-08-14 20:44:57 +00:00
my $ myfqdn = $ hash - > { MYFQDN } ? $ hash - > { MYFQDN } : "0.0.0.0" ;
2017-08-16 22:32:44 +00:00
my $ lf = AttrVal ( $ name , "logFormat" , "IETF" ) ;
2018-08-08 20:42:59 +00:00
my $ tag = AttrVal ( $ name , "contDelimiter" , "" ) ; # Trennzeichen vor Content (z.B. für Synology nötig)
2017-08-16 22:32:44 +00:00
my $ data ;
2017-08-25 08:28:14 +00:00
return undef , undef if ( ! $ otp ) ;
2018-08-01 19:20:56 +00:00
my $ pid = $ hash - > { SEQNO } ; # PayloadID zur Nachverfolgung der Eventabfolge
2017-08-25 08:28:14 +00:00
$ hash - > { SEQNO } + + ;
2017-08-16 22:32:44 +00:00
my ( $ year , $ month , $ day ) = split ( "-" , $ date ) ;
if ( $ lf eq "BSD" ) {
# BSD Protokollformat https://tools.ietf.org/html/rfc3164
2017-08-27 10:11:05 +00:00
$ time = ( split ( /\./ , $ time ) ) [ 0 ] if ( $ time =~ m/\./ ) ; # msec ist nicht erlaubt
2018-08-01 19:20:56 +00:00
$ month = $ Log2Syslog_BSDMonth { $ month } ; # Monatsmapping, z.B. 01 -> Jan
$ day =~ s/0/ / if ( $ day =~ m/^0.*$/ ) ; # in Tagen < 10 muss 0 durch Space ersetzt werden
$ ident = substr ( $ ident , 0 , $ RFC3164len { TAG } ) ; # Länge TAG Feld begrenzen
2017-08-16 22:32:44 +00:00
no warnings 'uninitialized' ;
2018-08-14 20:44:57 +00:00
$ ident = $ ident . "[$hash->{SEQNO}]:" ;
2018-08-08 20:42:59 +00:00
$ data = "<$prival>$month $day $time $myhost $ident $tag$otp" ;
2017-08-16 22:32:44 +00:00
use warnings ;
2018-08-01 19:20:56 +00:00
$ data = substr ( $ data , 0 , ( $ RFC3164len { DL } - 1 ) ) ; # Länge Total begrenzen
2017-08-16 22:32:44 +00:00
}
if ( $ lf eq "IETF" ) {
2017-08-25 08:28:14 +00:00
# IETF Protokollformat https://tools.ietf.org/html/rfc5424
2018-08-01 19:20:56 +00:00
my $ IETFver = 1 ; # Version von syslog Protokoll Spec RFC5424
my $ mid = "FHEM" ; # message ID, identify protocol of message, e.g. for firewall filter
my $ tim = $ date . "T" . $ time ;
my $ sdfield = "[version\@Log2Syslog version=\"$hash->{VERSION}\"]" ;
$ otp = Encode:: encode_utf8 ( $ otp ) ;
# Längenbegrenzung nach RFC5424
$ ident = substr ( $ ident , 0 , ( $ RFC5425len { ID } - 1 ) ) ;
$ pid = substr ( $ pid , 0 , ( $ RFC5425len { PID } - 1 ) ) ;
$ mid = substr ( $ mid , 0 , ( $ RFC5425len { MID } - 1 ) ) ;
2018-08-14 20:44:57 +00:00
$ myfqdn = substr ( $ myfqdn , 0 , ( $ RFC5425len { HST } - 1 ) ) ;
2018-08-01 19:20:56 +00:00
no warnings 'uninitialized' ;
if ( $ IETFver == 1 ) {
2018-08-14 20:44:57 +00:00
$ data = "<$prival>$IETFver $tim $myfqdn $ident $pid $mid $sdfield $tag$otp" ;
2018-08-01 19:20:56 +00:00
}
2017-08-16 22:32:44 +00:00
use warnings ;
}
2017-08-27 10:11:05 +00:00
if ( $ data =~ /\s$/ ) { $ data =~ s/\s$// ; }
2018-08-01 19:20:56 +00:00
my $ dl = length ( $ data ) ; # Länge muss ! für TLS stimmen, sonst keine Ausgabe !
2017-08-25 08:28:14 +00:00
# wenn Transport Layer Security (TLS) -> Transport Mapping for Syslog https://tools.ietf.org/pdf/rfc5425.pdf
if ( AttrVal ( $ name , "TLS" , 0 ) ) {
$ data = "$dl $data" ;
2018-08-01 19:20:56 +00:00
$ data = substr ( $ data , 0 , ( $ RFC5425len { DL } - 1 ) ) ; # Länge Total begrenzen
Log2Syslog_Log3slog ( $ name , 4 , "$name - SSL-Payload created with length: " . ( ( $ dl > ( $ RFC5425len { DL } - 1 ) ) ? ( $ RFC5425len { DL } - 1 ) : $ dl ) ) ;
2017-08-25 08:28:14 +00:00
}
2017-08-22 06:41:25 +00:00
my $ ldat = ( $ dl > 130 ) ? ( substr ( $ data , 0 , 130 ) . " ..." ) : $ data ;
2017-08-27 10:11:05 +00:00
Log2Syslog_Log3slog ( $ name , 4 , "$name - Payload sequence $pid created:\n$ldat" ) ;
2017-08-22 06:41:25 +00:00
2017-08-25 08:28:14 +00:00
return ( $ data , $ pid ) ;
2017-08-16 22:32:44 +00:00
}
2017-08-20 08:19:32 +00:00
###############################################################################
# eigene Log3-Ableitung - Schleife vermeiden
###############################################################################
2017-08-27 10:11:05 +00:00
sub Log2Syslog_Log3slog ($$$) {
2017-08-20 08:19:32 +00:00
my ( $ dev , $ loglevel , $ text ) = @ _ ;
our ( $ logopened , $ currlogfile ) ;
$ dev = $ dev - > { NAME } if ( defined ( $ dev ) && ref ( $ dev ) eq "HASH" ) ;
if ( defined ( $ dev ) &&
defined ( $ attr { $ dev } ) &&
defined ( my $ devlevel = $ attr { $ dev } { verbose } ) ) {
return if ( $ loglevel > $ devlevel ) ;
} else {
return if ( $ loglevel > $ attr { global } { verbose } ) ;
}
my ( $ seconds , $ microseconds ) = gettimeofday ( ) ;
my @ t = localtime ( $ seconds ) ;
my $ nfile = ResolveDateWildcards ( $ attr { global } { logfile } , @ t ) ;
OpenLogfile ( $ nfile ) if ( ! $ currlogfile || $ currlogfile ne $ nfile ) ;
my $ tim = sprintf ( "%04d.%02d.%02d %02d:%02d:%02d" ,
$ t [ 5 ] + 1900 , $ t [ 4 ] + 1 , $ t [ 3 ] , $ t [ 2 ] , $ t [ 1 ] , $ t [ 0 ] ) ;
if ( $ attr { global } { mseclog } ) {
$ tim . = sprintf ( ".%03d" , $ microseconds / 1000 ) ;
}
if ( $ logopened ) {
print LOG "$tim $loglevel: $text\n" ;
} else {
print "$tim $loglevel: $text\n" ;
}
return undef ;
}
2017-08-25 08:28:14 +00:00
###############################################################################
# Bestimmung Übertragungsrate
###############################################################################
2017-08-27 10:11:05 +00:00
sub Log2Syslog_trate ($) {
2017-08-25 08:28:14 +00:00
my ( $ hash ) = @ _ ;
2017-08-27 10:11:05 +00:00
my $ name = $ hash - > { NAME } ;
2017-08-27 10:50:18 +00:00
my $ rerun = AttrVal ( $ name , "rateCalcRerun" , 60 ) ;
2017-08-25 08:28:14 +00:00
if ( $ hash - > { HELPER } { LTIME } + 60 <= time ( ) ) {
my $ div = ( time ( ) - $ hash - > { HELPER } { LTIME } ) / 60 ;
my $ spm = sprintf "%.0f" , ( $ hash - > { SEQNO } - $ hash - > { HELPER } { OLDSEQNO } ) / $ div ;
$ hash - > { HELPER } { OLDSEQNO } = $ hash - > { SEQNO } ;
$ hash - > { HELPER } { LTIME } = time ( ) ;
2017-08-27 10:11:05 +00:00
my $ ospm = ReadingsVal ( $ name , "Transfered_logs_per_minute" , 0 ) ;
2017-08-25 08:28:14 +00:00
if ( $ spm != $ ospm ) {
readingsSingleUpdate ( $ hash , "Transfered_logs_per_minute" , $ spm , 1 ) ;
2017-08-27 10:11:05 +00:00
} else {
readingsSingleUpdate ( $ hash , "Transfered_logs_per_minute" , $ spm , 0 ) ;
}
2017-08-25 08:28:14 +00:00
}
2017-08-27 10:11:05 +00:00
RemoveInternalTimer ( $ hash , "Log2Syslog_trate" ) ;
InternalTimer ( gettimeofday ( ) + $ rerun , "Log2Syslog_trate" , $ hash , 0 ) ;
2018-08-01 19:20:56 +00:00
2017-08-25 08:28:14 +00:00
return ;
}
2018-08-03 08:57:49 +00:00
###############################################################################
# Peer IP-Adresse und Host ermitteln (Sender der Message)
###############################################################################
sub Log2Syslog_evalPeer ($) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ socket = $ hash - > { SERVERSOCKET } ;
2018-08-09 06:52:31 +00:00
my ( $ phost , $ paddr ) ;
2018-08-03 08:57:49 +00:00
my ( $ pport , $ pipaddr ) = sockaddr_in ( $ socket - > peername ) ;
2018-08-08 20:42:59 +00:00
$ phost = gethostbyaddr ( $ pipaddr , AF_INET ) ;
$ paddr = inet_ntoa ( $ pipaddr ) ;
2018-08-13 21:55:35 +00:00
no warnings 'uninitialized' ;
2018-08-09 06:52:31 +00:00
Log2Syslog_Log3slog ( $ hash , 5 , "Log2Syslog $name - message peerhost: $phost,$paddr" ) ;
2018-08-13 21:55:35 +00:00
use warnings ;
2018-08-03 08:57:49 +00:00
return ( $ phost , $ paddr ) ;
}
2017-08-16 22:32:44 +00:00
1 ;
= pod
= item helper
2018-08-01 19:20:56 +00:00
= item summary forwards FHEM system logs and / or events to a syslog server or act as an syslog server itself
= item summary_DE sendet FHEM Systemlogs und / oder Events an einen Syslog - Server bzw . agiert selbst als Syslog - Server
2017-08-16 22:32:44 +00:00
= begin html
< a name = "Log2Syslog" > </a>
<h3> Log2Syslog </h3>
<ul>
2017-08-25 08:28:14 +00:00
Send FHEM system log entries and / or FHEM events to an external syslog server . <br>
The syslog protocol has been implemented according the specifications of < a href = "https://tools.ietf.org/html/rfc5424" > RFC5424 ( IETF ) </a> ,
2018-08-01 19:20:56 +00:00
< a href = "https://tools.ietf.org/html/rfc3164" > RFC3164 ( BSD ) </a> and the TLS transport protocol according to
2017-08-25 08:28:14 +00:00
< a href = "https://tools.ietf.org/pdf/rfc5425.pdf" > RFC5425 </a> . <br>
<br>
2017-08-16 22:32:44 +00:00
<b> Prerequisits </b>
<ul>
<br/>
The additional perl module "IO::Socket::INET" must be installed on your system . <br>
Install this package from cpan or by <br> <br>
<code> apt - get install libio - socket - multicast - perl ( only on Debian based installations ) </code> <br>
</ul>
<br>
< a name = "Log2Syslogdefine" > </a>
<b> Define </b>
<ul>
<br>
2017-08-18 19:51:33 +00:00
<code> define & lt ; name & gt ; Log2Syslog & lt ; destination host & gt ; [ ident: & lt ; ident & gt ; ] [ event: & lt ; regexp & gt ; ] [ fhem: & lt ; regexp & gt ; ] </code> <br>
2017-08-16 22:32:44 +00:00
<br>
& lt ; destination host & gt ; = host where the syslog server is running <br>
2017-08-18 19:51:33 +00:00
[ ident: & lt ; ident & gt ; ] = optional program identifier . If not set the device name will be used as default <br>
2017-08-16 23:06:15 +00:00
[ event: & lt ; regexp & gt ; ] = optional regex to filter events for logging <br>
[ fhem: & lt ; regexp & gt ; ] = optional regex to filter fhem system log for logging <br> <br>
2017-08-16 22:32:44 +00:00
After definition the new device sends all new appearing fhem systemlog entries and events to the destination host ,
port = 514 / UDP format : IETF , immediately without further settings if the regex for fhem or event were set . <br>
2017-08-19 15:09:53 +00:00
Without setting regex no fhem system log or event log will be forwarded . <br> <br>
The verbose level of FHEM system logs will convert into equivalent syslog severity level . <br>
Thurthermore the message text will be scanned for signal terms "warning" and "error" ( with case insensitivity ) .
Dependent off the severity will be set equivalent as well . If a severity is already set by verbose level , it wil be overwritten
by the level according to the signal term found in the message text . <br> <br>
<b> Lookup table Verbose - Level to Syslog severity level: </b> <br> <br>
<ul>
<table>
<colgroup> < col width = 40 % > < col width = 60 % > < / colgroup >
2018-08-01 19:20:56 +00:00
<tr> <td> <b> verbose - Level </b> </td> <td> <b> Severity in Syslog </b> </td> </tr>
2017-08-19 15:09:53 +00:00
<tr> <td> 0 </td> <td> Critical </td> </tr>
<tr> <td> 1 </td> <td> Error </td> </tr>
<tr> <td> 2 </td> <td> Warning </td> </tr>
<tr> <td> 3 </td> <td> Notice </td> </tr>
<tr> <td> 4 </td> <td> Informational </td> </tr>
<tr> <td> 5 </td> <td> Debug </td> </tr>
</table>
</ul>
<br>
2017-08-16 22:32:44 +00:00
<br>
Example to log anything: <br>
<br/>
2017-08-18 19:51:33 +00:00
<code> define splunklog Log2Syslog fhemtest 192.168 .2 .49 ident:Test event: . * fhem: . * </code> <br>
2017-08-16 22:32:44 +00:00
<br/>
2017-08-18 19:51:33 +00:00
will produce output like this raw example of a splunk syslog server: <br/>
<pre> Aug 18 21 : 06 : 46 fhemtest . myds . me 1 2017 - 08 - 18 T21:06:46 fhemtest . myds . me Test_event 13339 FHEM - : LogDB sql_processing_time: 0.2306
Aug 18 21 : 06 : 46 fhemtest . myds . me 1 2017 - 08 - 18 T21:06:46 fhemtest . myds . me Test_event 13339 FHEM - : LogDB background_processing_time: 0.2397
Aug 18 21 : 06 : 45 fhemtest . myds . me 1 2017 - 08 - 18 T21:06:45 fhemtest . myds . me Test_event 13339 FHEM - : LogDB CacheUsage: 21
Aug 18 21 : 08 : 27 fhemtest . myds . me 1 2017 - 08 - 18 T21:08:27 .760 fhemtest . myds . me Test_fhem 13339 FHEM - : 4 : CamTER - Informations of camera Terrasse retrieved
Aug 18 21 : 08 : 27 fhemtest . myds . me 1 2017 - 08 - 18 T21:08:27 .095 fhemtest . myds . me Test_fhem 13339 FHEM - : 4 : CamTER - CAMID already set - ignore get camid
</pre>
2017-08-27 10:11:05 +00:00
The structure of the payload differs dependent of the used logFormat . <br> <br>
<b> logFormat IETF: </b> <br> <br>
2018-08-01 19:20:56 +00:00
"<PRIVAL>VERSION TIME MYHOST IDENT PID MID [SD-FIELD] :MESSAGE" <br> <br>
2017-08-27 10:11:05 +00:00
<ul>
<table>
<colgroup> < col width = 10 % > < col width = 90 % > < / colgroup >
<tr> <td> PRIVAL </td> <td> priority value ( coded from "facility" and "severity" ) </td> </tr>
<tr> <td> TIME </td> <td> timestamp according to RFC5424 </td> </tr>
<tr> <td> MYHOST </td> <td> Internal MYHOST </td> </tr>
<tr> <td> IDENT </td> <td> ident - Tag from DEF if set , or else the own device name . The statement will be completed by "_fhem" ( FHEM - Log ) respectively "_event" ( Event - Log ) . </td> </tr>
<tr> <td> PID </td> <td> sequential Payload - ID </td> </tr>
<tr> <td> MID </td> <td> fix value "FHEM" </td> </tr>
<tr> <td> MESSAGE </td> <td> the dataset to transfer </td> </tr>
</table>
</ul>
<br>
<b> logFormat BSD: </b> <br> <br>
"<PRIVAL>MONAT TAG TIME MYHOST IDENT: : MESSAGE" <br> <br>
<ul>
<table>
<colgroup> < col width = 10 % > < col width = 90 % > < / colgroup >
<tr> <td> PRIVAL </td> <td> priority value ( coded from "facility" and "severity" ) </td> </tr>
<tr> <td> MONAT </td> <td> month according to RFC3164 </td> </tr>
<tr> <td> TAG </td> <td> day of month according to RFC3164 </td> </tr>
<tr> <td> TIME </td> <td> timestamp according to RFC3164 </td> </tr>
<tr> <td> MYHOST </td> <td> Internal MYHOST </td> </tr>
<tr> <td> IDENT </td> <td> ident - Tag from DEF if set , or else the own device name . The statement will be completed by "_fhem" ( FHEM - Log ) respectively "_event" ( Event - Log ) . </td> </tr>
<tr> <td> MESSAGE </td> <td> the dataset to transfer </td> </tr>
</table>
</ul>
<br>
2017-08-25 08:28:14 +00:00
2017-08-16 22:32:44 +00:00
</ul>
2017-08-25 08:28:14 +00:00
<br>
2017-08-16 22:32:44 +00:00
2018-08-01 19:20:56 +00:00
< a name = "Log2SyslogGet" > </a>
<b> Get </b>
<ul>
<br>
<li> <code> certinfo </code> <br>
<br>
Show informations about the server certificate if a TLS - session was created ( Reading "SSL_Version" isn ' t "n.a." ) .
</li> <br>
</ul>
<br>
2017-08-16 22:32:44 +00:00
< a name = "Log2Syslogattr" > </a>
<b> Attributes </b>
<ul>
<br/>
< a name = "addTimestamp" > </a>
<li> <code> addTimestamp [ 0 | 1 ] </code> <br>
<br/>
If set to 1 , fhem timestamps will be logged too . <br/>
Default behavior is to not log these timestamps , because syslog uses own timestamps . <br/>
Maybe useful if mseclog is activated in fhem . <br/>
<br/>
2017-08-18 19:51:33 +00:00
Example output ( raw ) of a Splunk syslog server: <br>
<pre> Aug 18 21 : 26 : 55 fhemtest . myds . me 1 2017 - 08 - 18 T21:26:55 fhemtest . myds . me Test_event 13339 FHEM - : 2017 - 08 - 18 21 : 26 : 55 USV state: OL
Aug 18 21 : 26 : 54 fhemtest . myds . me 1 2017 - 08 - 18 T21:26:54 fhemtest . myds . me Test_event 13339 FHEM - : 2017 - 08 - 18 21 : 26 : 54 Bezug state: done
Aug 18 21 : 26 : 54 fhemtest . myds . me 1 2017 - 08 - 18 T21:26:54 fhemtest . myds . me Test_event 13339 FHEM - : 2017 - 08 - 18 21 : 26 : 54 recalc_Bezug state: Next: 21 : 31 : 59
</pre>
2017-08-16 22:32:44 +00:00
</li> <br>
<li> <code> addStateEvent [ 0 | 1 ] </code> <br>
<br>
If set to 1 , events will be completed with "state" if a state - event appears . <br/>
Default behavior is without getting "state" .
</li> <br>
2017-08-18 19:51:33 +00:00
<li> <code> disable [ 0 | 1 ] </code> <br>
<br>
disables the device .
</li> <br>
2017-08-16 22:32:44 +00:00
<li> <code> logFormat [ BSD | IETF ] </code> <br>
<br>
Set the syslog protocol format . <br>
2017-08-17 20:20:38 +00:00
Default value is "IETF" if not specified .
</li> <br>
2017-08-16 22:32:44 +00:00
2017-08-27 10:11:05 +00:00
<li> <code> protocol [ TCP | UDP ] </code> <br>
2017-08-16 22:32:44 +00:00
<br>
2017-08-27 10:11:05 +00:00
Sets the socket protocol which should be used . You can choose UDP or TCP . <br>
2017-08-16 22:32:44 +00:00
Default value is "UDP" if not specified .
</li> <br>
<li> <code> port </code> <br>
<br>
2018-08-01 19:20:56 +00:00
The used port . For a Sender the default - port is 514 .
A Collector ( Syslog - Server ) uses the port 1514 per default .
2017-08-16 22:32:44 +00:00
</li> <br>
2017-08-27 10:50:18 +00:00
<li> <code> rateCalcRerun </code> <br>
2017-08-27 10:11:05 +00:00
<br>
Rerun cycle for calculation of log transfer rate ( Reading "Transfered_logs_per_minute" ) in seconds .
Default is 60 seconds .
</li> <br>
2018-08-01 19:20:56 +00:00
<li> <code> ssldebug </code> <br>
<br>
Debugging level of SSL messages . <br> <br>
<ul>
<li> 0 - No debugging ( default ) . </li>
<li> 1 - Print out errors from < a href = "http://search.cpan.org/~sullr/IO-Socket-SSL-2.056/lib/IO/Socket/SSL.pod" > IO::Socket:: SSL </a> and ciphers from < a href = "http://search.cpan.org/~mikem/Net-SSLeay-1.85/lib/Net/SSLeay.pod" > Net:: SSLeay </a> . </li>
<li> 2 - Print also information about call flow from < a href = "http://search.cpan.org/~sullr/IO-Socket-SSL-2.056/lib/IO/Socket/SSL.pod" > IO::Socket:: SSL </a> and progress information from < a href = "http://search.cpan.org/~mikem/Net-SSLeay-1.85/lib/Net/SSLeay.pod" > Net:: SSLeay </a> . </li>
<li> 3 - Print also some data dumps from < a href = "http://search.cpan.org/~sullr/IO-Socket-SSL-2.056/lib/IO/Socket/SSL.pod" > IO::Socket:: SSL </a> and from < a href = "http://search.cpan.org/~mikem/Net-SSLeay-1.85/lib/Net/SSLeay.pod" > Net:: SSLeay </a> . </li>
</ul>
</li> <br>
2017-08-27 10:11:05 +00:00
2018-08-01 19:20:56 +00:00
<li> <code> TLS </code> <br>
<br>
A secured connection to Syslog - server is used . The protocol will be switched to TCP automatically .
</li> <br>
2017-08-25 08:28:14 +00:00
<li> <code> timeout </code> <br>
<br>
2018-08-01 19:20:56 +00:00
Timeout for connection to the destination syslog server ( TCP ) . Only valid in Sender - mode . Default: 0.5 seconds .
2017-08-25 08:28:14 +00:00
</li> <br>
2017-08-22 06:41:25 +00:00
<li> <code> verbose </code> <br>
<br>
To avoid loops , the output of verbose level of the Log2Syslog - Devices will only be reported into the local FHEM Logfile and
no forwarded .
</li> <br>
2017-08-16 22:32:44 +00:00
</ul>
2017-08-27 10:38:38 +00:00
<br>
< a name = "Log2Syslogreadings" > </a>
<b> Readings </b>
<ul>
<br>
<table>
<colgroup> < col width = 40 % > < col width = 60 % > < / colgroup >
<tr> <td> <b> SSL_Algorithm </b> </td> <td> used SSL algorithm if SSL is enabled and active </td> </tr>
<tr> <td> <b> SSL_Version </b> </td> <td> the used TLS - version if encryption is enabled and is active </td> </tr>
<tr> <td> <b> Transfered_logs_per_minute </b> </td> <td> the average number of forwarded logs /events per minute </ td > </tr>
</table>
<br>
</ul>
2017-08-16 22:32:44 +00:00
</ul>
= end html
= begin html_DE
< a name = "Log2Syslog" > </a>
<h3> Log2Syslog </h3>
<ul>
2018-08-01 19:20:56 +00:00
Sendet das Modul FHEM Systemlog Einträge und / oder Events an einen externen Syslog - Server weiter oder agiert als
Syslog - Server um Syslog - Meldungen anderer Geräte zu empfangen . <br>
2017-08-25 08:28:14 +00:00
Die Implementierung des Syslog - Protokolls erfolgte entsprechend den Vorgaben von < a href = "https://tools.ietf.org/html/rfc5424" > RFC5424 ( IETF ) </a> ,
< a href = "https://tools.ietf.org/html/rfc3164" > RFC3164 ( BSD ) </a> sowie dem TLS Transport Protokoll nach
< a href = "https://tools.ietf.org/pdf/rfc5425.pdf" > RFC5425 </a> . <br>
<br>
2017-08-16 22:32:44 +00:00
<b> Voraussetzungen </b>
<ul>
<br/>
Es wird das Perl Modul "IO::Socket::INET" benötigt und muss installiert sein . <br>
Das Modul kann über CPAN oder mit <br> <br>
<code> apt - get install libio - socket - multicast - perl ( auf Debian Linux Systemen ) </code> <br> <br>
installiert werden .
</ul>
<br/>
< a name = "Log2Syslogdefine" > </a>
2018-08-05 19:04:41 +00:00
<b> Definition und Verwendung </b>
2017-08-16 22:32:44 +00:00
<ul>
<br>
2018-08-01 19:20:56 +00:00
Je nach Verwendungszweck kann ein Syslog - Server ( MODEL Collector ) oder ein Syslog - Client ( MODEL Sender ) definiert
werden . <br>
2018-08-06 21:02:42 +00:00
Der Collector empfängt Meldungen im Syslog - Format anderer Geräte und generiert daraus Events / Readings zur Weiterverarbeitung in
2018-08-01 19:20:56 +00:00
FHEM . Das Sender - Device leitet FHEM Systemlog Einträge und / oder Events an einen externen Syslog - Server weiter . <br>
2018-08-05 19:04:41 +00:00
</ul>
2018-08-01 19:20:56 +00:00
2018-08-05 19:04:41 +00:00
<br>
<b> <h4> Der Collector ( Syslog - Server ) </h4> </b>
<ul>
2018-08-01 19:20:56 +00:00
<b> Definition eines Collectors </b>
<br>
<ul>
<br>
<code> define & lt ; name & gt ; Log2Syslog </code> <br>
<br>
</ul>
2018-08-03 15:09:44 +00:00
Die Definition benötigt keine weiteren Parameter .
2018-08-05 19:04:41 +00:00
In der Grundeinstellung wird der Syslog - Server mit dem Port = 1514 / UDP und dem Parsingprofil "IETF" initialisiert .
Mit dem < a href = "#Log2Syslogattr" > Attribut </a> "parseProfile" können alternativ andere Formate ( z . B . BSD ) ausgewählt werden .
2018-08-03 15:09:44 +00:00
Der Syslog - Server ist sofort betriebsbereit , parst die Syslog - Daten entsprechend der Richlinien nach RFC5424 und generiert aus den
eingehenden Syslog - Meldungen FHEM - Events . <br> <br>
2017-08-16 22:32:44 +00:00
<br>
2018-08-01 19:20:56 +00:00
<b> Beispiel für einen Collector: </b> <br>
<ul>
<br>
<code> define SyslogServer Log2Syslog </code> <br>
<br>
</ul>
2018-08-05 19:04:41 +00:00
Im Eventmonitor können die generierten Events kontrolliert werden . <br>
<br>
Beispiel von generierten Events mit Attribut parseProfile = IETF: <br>
<br>
<code>
2018 - 07 - 31 17 : 07 : 24.382 Log2Syslog SyslogServer HOST: fhem . myds . me || FAC: syslog || SEV: Notice || ID: Prod_event || CONT: USV state: OL <br>
2018 - 07 - 31 17 : 07 : 24.858 Log2Syslog SyslogServer HOST: fhem . myds . me || FAC: syslog || SEV: Notice || ID: Prod_event || CONT: HMLAN2 loadLvl: low <br>
</code>
<br>
2018-08-01 19:20:56 +00:00
Zwischen den einzelnen Feldern wird der Trenner "||" verwendet .
2018-08-05 19:04:41 +00:00
Die Bedeutung der Felder in diesem Beispiel sind:
2018-08-01 19:20:56 +00:00
<br> <br>
<ul>
<table>
<colgroup> < col width = 20 % > < col width = 80 % > < / colgroup >
<tr> <td> <b> HOST </b> </td> <td> der Sender des Datensatzes </td> </tr>
<tr> <td> <b> FAC </b> </td> <td> Facility ( Kategorie ) nach RFC5424 </td> </tr>
<tr> <td> <b> SEV </b> </td> <td> Severity ( Schweregrad ) nach RFC5424 </td> </tr>
<tr> <td> <b> ID </b> </td> <td> Ident - Tag </td> </tr>
2018-08-05 19:04:41 +00:00
<tr> <td> <b> CONT </b> </td> <td> der Nachrichtenteil der empfangenen Meldung </td> </tr>
2018-08-01 19:20:56 +00:00
</table>
2018-08-03 15:09:44 +00:00
</ul>
<br>
2018-08-05 19:04:41 +00:00
Der Timestamp der generierten Events wird aus den Syslogmeldungen geparst . Sollte diese Information nicht mitgeliefert
werden , wird der aktuelle Timestamp des Systems verwendet . <br>
2018-08-03 15:09:44 +00:00
Der Name des Readings im generierten Event entspricht dem aus der Syslogmeldung geparsten Hostnamen .
2018-08-05 19:04:41 +00:00
Ist der Hostname in der Meldung nicht enthalten , wird die IP - Adresse des Senders aus dem Netzwerk Interface abgerufen und
der Hostname ermittelt sofern möglich .
In diesem Fall wird der ermittelte Hostname bzw . die IP - Adresse als Reading im Event genutzt .
2018-08-03 15:09:44 +00:00
<br>
2018-08-05 19:04:41 +00:00
Nach der Definition des Collectors werden die Syslog - Meldungen im IETF - Format gemäß RFC5424 erwartet . Werden die Daten
2018-08-10 12:40:19 +00:00
nicht in diesem Format geliefert bzw . können nicht geparst werden , erscheint im Reading "state" die Meldung
<b> "parse error - see logfile" </b> und die empfangenen Syslog - Daten werden im Logfile im raw - Format ausgegeben . <br>
2018-08-05 19:04:41 +00:00
In diesem Fall kann mit dem < a href = "#Log2Syslogattr" > Attribut </a> "parseProfile" ein anderes vordefiniertes Parsing - Profil
eingestellt bzw . ein eigenes Profil definiert werden . <br> <br>
2018-08-01 19:20:56 +00:00
2018-08-05 19:04:41 +00:00
Zur Definition einer <b> eigenen Parsingfunktion </b> wird
"parseProfile = ParseFn" eingestellt und im < a href = "#Log2Syslogattr" > Attribut </a> "parseFn" eine spezifische
Parsingfunktion hinterlegt . <br>
Die im Event verwendeten Felder und deren Reihenfolge können aus einem Wertevorrat mit dem
< a href = "#Log2Syslogattr" > Attribut </a> "outputFields" bestimmt werden . Je nach verwendeten Parsingprofil können alle oder
2018-08-06 21:02:42 +00:00
nur eine Untermenge der verfügbaren Felder verwendet werden . Näheres dazu in der Beschreibung des Attributes "parseProfile" . <br>
<br>
2018-08-13 21:55:35 +00:00
Das Verhalten der Eventgenerierung kann mit dem < a href = "#Log2Syslogattr" > Attribut </a> "makeEvent" angepasst werden . <br>
2018-08-05 19:04:41 +00:00
</ul>
<br>
<b> <h4> Der Sender ( Syslog - Client ) </h4> </b>
<ul>
2018-08-01 19:20:56 +00:00
<b> Definition eines Senders </b>
<br>
<ul>
<br>
<code> define & lt ; name & gt ; Log2Syslog & lt ; Zielhost & gt ; [ ident: & lt ; ident & gt ; ] [ event: & lt ; regexp & gt ; ] [ fhem: & lt ; regexp & gt ; ] </code> <br>
<br>
</ul>
<ul>
<table>
<colgroup> < col width = 20 % > < col width = 80 % > < / colgroup >
<tr> <td> <b> & lt ; Zielhost & gt ; </b> </td> <td> Host ( Name oder IP - Adresse ) auf dem der Syslog - Server läuft </td> </tr>
<tr> <td> <b> [ ident: & lt ; ident & gt ; ] </b> </td> <td> optionaler Programm Identifier . Wenn nicht gesetzt wird per default der Devicename benutzt . </td> </tr>
<tr> <td> <b> [ event: & lt ; regexp & gt ; ] </b> </td> <td> optionaler regulärer Ausdruck zur Filterung von Events zur Weiterleitung </td> </tr>
<tr> <td> <b> [ fhem: & lt ; regexp & gt ; ] </b> </td> <td> optionaler regulärer Ausdruck zur Filterung von FHEM Logs zur Weiterleitung </td> </tr>
</table>
</ul>
<br> <br>
2017-08-16 22:32:44 +00:00
Direkt nach der Definition sendet das neue Device alle neu auftretenden FHEM Systemlog Einträge und Events ohne weitere
2017-08-19 15:09:53 +00:00
Einstellungen an den Zielhost , Port = 514 /UDP Format=IETF, wenn reguläre Ausdrücke für Events/ FHEM angegeben wurden . <br>
Wurde kein Regex gesetzt , erfolgt keine Weiterleitung von Events oder FHEM Systemlogs . <br> <br>
Die Verbose - Level der FHEM Systemlogs werden in entsprechende Schweregrade der Syslog - Messages umgewandelt . <br>
Weiterhin wird der Meldungstext der FHEM Systemlogs und Events nach den Signalwörtern "warning" und "error" durchsucht
2018-08-01 19:20:56 +00:00
( Groß - / Kleinschreibung wird nicht beachtet ) . Davon abhängig wird der Schweregrad ebenfalls äquivalent gesetzt und übersteuert
2017-08-19 15:09:53 +00:00
einen eventuell bereits durch Verbose - Level gesetzten Schweregrad . <br> <br>
<b> Umsetzungstabelle Verbose - Level in Syslog - Schweregrad Stufe: </b> <br> <br>
<ul>
<table>
<colgroup> < col width = 40 % > < col width = 60 % > < / colgroup >
<tr> <td> <b> Verbose - Level </b> </td> <td> <b> Schweregrad in Syslog </b> </td> </tr>
<tr> <td> 0 </td> <td> Critical </td> </tr>
<tr> <td> 1 </td> <td> Error </td> </tr>
<tr> <td> 2 </td> <td> Warning </td> </tr>
<tr> <td> 3 </td> <td> Notice </td> </tr>
<tr> <td> 4 </td> <td> Informational </td> </tr>
<tr> <td> 5 </td> <td> Debug </td> </tr>
</table>
</ul>
<br>
2017-08-16 22:32:44 +00:00
<br>
2018-08-01 19:20:56 +00:00
<b> Beispiel für einen Sender: </b> <br>
<ul>
<br>
2017-08-18 19:51:33 +00:00
<code> define splunklog Log2Syslog fhemtest 192.168 .2 .49 ident:Test event: . * fhem: . * </code> <br/>
2018-08-01 19:20:56 +00:00
<br>
</ul>
Es werden alle Events weitergeleitet wie deses Beispiel der raw - Ausgabe eines Splunk Syslog Servers zeigt: <br/>
<pre>
2018-08-03 15:09:44 +00:00
Aug 18 21 : 06 : 46 fhemtest . myds . me 1 2017 - 08 - 18 T21:06:46 fhemtest . myds . me Test_event 13339 FHEM [ version @ Log2Syslog version = "4.2.0" ] : LogDB sql_processing_time: 0.2306
Aug 18 21 : 06 : 46 fhemtest . myds . me 1 2017 - 08 - 18 T21:06:46 fhemtest . myds . me Test_event 13339 FHEM [ version @ Log2Syslog version = "4.2.0" ] : LogDB background_processing_time: 0.2397
Aug 18 21 : 06 : 45 fhemtest . myds . me 1 2017 - 08 - 18 T21:06:45 fhemtest . myds . me Test_event 13339 FHEM [ version @ Log2Syslog version = "4.2.0" ] : LogDB CacheUsage: 21
Aug 18 21 : 08 : 27 fhemtest . myds . me 1 2017 - 08 - 18 T21:08:27 .760 fhemtest . myds . me Test_fhem 13339 FHEM [ version @ Log2Syslog version = "4.2.0" ] : 4 : CamTER - Informations of camera Terrasse retrieved
Aug 18 21 : 08 : 27 fhemtest . myds . me 1 2017 - 08 - 18 T21:08:27 .095 fhemtest . myds . me Test_fhem 13339 FHEM [ version @ Log2Syslog version = "4.2.0" ] : 4 : CamTER - CAMID already set - ignore get camid
2017-08-18 19:51:33 +00:00
</pre>
2017-08-16 22:32:44 +00:00
2017-08-25 08:28:14 +00:00
Der Aufbau der Payload unterscheidet sich je nach verwendeten logFormat . <br> <br>
<b> logFormat IETF: </b> <br> <br>
2018-08-01 19:20:56 +00:00
"<PRIVAL>VERSION TIME MYHOST IDENT PID MID [SD-FIELD] :MESSAGE" <br> <br>
2017-08-25 08:28:14 +00:00
<ul>
<table>
<colgroup> < col width = 10 % > < col width = 90 % > < / colgroup >
2018-08-03 15:09:44 +00:00
<tr> <td> PRIVAL </td> <td> Priority Wert ( kodiert aus "facility" und "severity" ) </td> </tr>
<tr> <td> TIME </td> <td> Timestamp nach RFC5424 </td> </tr>
<tr> <td> MYHOST </td> <td> Internal MYHOST </td> </tr>
<tr> <td> IDENT </td> <td> Ident - Tag aus DEF wenn angegeben , sonst der eigene Devicename . Die Angabe wird mit "_fhem" ( FHEM - Log ) bzw . "_event" ( Event - Log ) ergänzt . </td> </tr>
<tr> <td> PID </td> <td> fortlaufende Payload - ID </td> </tr>
<tr> <td> MID </td> <td> fester Wert "FHEM" </td> </tr>
<tr> <td> [ SD - FIELD ] </td> <td> Structured Data Feld . Enthält Informationen zur verwendeten Modulversion ( die Klammern "[]" sind Bestandteil des Feldes ) </td> </tr>
<tr> <td> MESSAGE </td> <td> der zu übertragende Datensatz </td> </tr>
2017-08-25 08:28:14 +00:00
</table>
</ul>
<br>
<b> logFormat BSD: </b> <br> <br>
"<PRIVAL>MONAT TAG TIME MYHOST IDENT: : MESSAGE" <br> <br>
<ul>
<table>
<colgroup> < col width = 10 % > < col width = 90 % > < / colgroup >
<tr> <td> PRIVAL </td> <td> Priority Wert ( kodiert aus "facility" und "severity" ) </td> </tr>
<tr> <td> MONAT </td> <td> Monatsangabe nach RFC3164 </td> </tr>
<tr> <td> TAG </td> <td> Tag des Monats nach RFC3164 </td> </tr>
<tr> <td> TIME </td> <td> Zeitangabe nach RFC3164 </td> </tr>
<tr> <td> MYHOST </td> <td> Internal MYHOST </td> </tr>
<tr> <td> IDENT </td> <td> Ident - Tag aus DEF wenn angegeben , sonst der eigene Devicename . Die Angabe wird mit "_fhem" ( FHEM - Log ) bzw . "_event" ( Event - Log ) ergänzt . </td> </tr>
<tr> <td> MESSAGE </td> <td> der zu übertragende Datensatz </td> </tr>
</table>
</ul>
<br>
</ul>
<br> <br>
2018-08-08 06:36:04 +00:00
< a name = "Log2SyslogSet" > </a>
<b> Set </b>
<ul>
<br>
<ul>
<li> <b> sendTestMessage [ & lt ; Message & gt ; ] </b> <br>
<br>
Mit einem Devicetyp "Sender" kann abhängig vom Attribut "logFormat" eine Testnachricht im BSD - bzw . IETF - Format
gesendet werden . Wird eine optionale eigene & lt ; Message & gt ; angegeben , wird diese Nachricht im raw - Format ohne
Formatanpassung ( BSD / IETF ) gesendet . Das Attribut "disable = maintenance" legt fest , dass keine Daten ausser eine
Testnachricht an den Empfänger gesendet wird .
</li>
</ul>
<br>
</ul>
<br>
2018-08-01 19:20:56 +00:00
< a name = "Log2SyslogGet" > </a>
<b> Get </b>
<ul>
<br>
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> certinfo </b> <br>
2018-08-01 19:20:56 +00:00
<br>
Zeigt Informationen zum Serverzertifikat wenn eine TLS - Session aufgebaut wurde ( Reading "SSL_Version" ist nicht "n.a." ) .
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
2018-08-01 19:20:56 +00:00
</ul>
<br>
2018-08-08 06:36:04 +00:00
2017-08-16 22:32:44 +00:00
< a name = "Log2Syslogattr" > </a>
<b> Attribute </b>
<ul>
<br>
2018-08-05 19:04:41 +00:00
<ul>
2017-08-16 22:32:44 +00:00
< a name = "addTimestamp" > </a>
2018-08-05 19:04:41 +00:00
<li> <b> addTimestamp </b> <br>
2017-08-16 22:32:44 +00:00
<br/>
2018-08-05 19:04:41 +00:00
Das Attribut ist nur für "Sender" verwendbar . Wenn gesetzt , werden FHEM Timestamps im Content - Feld der Syslog - Meldung
mit übertragen . <br/>
Per default werden die Timestamps nicht im Content - Feld hinzugefügt , da innerhalb der Syslog - Meldungen im IETF - bzw .
BSD - Format bereits Zeitstempel gemäß RFC - Vorgabe erstellt werden . <br/>
2017-08-16 22:32:44 +00:00
Die Einstellung kann hilfeich sein wenn mseclog in FHEM aktiviert ist . <br/>
<br/>
2017-08-18 19:51:33 +00:00
Beispielausgabe ( raw ) eines Splunk Syslog Servers: <br/>
<pre> Aug 18 21 : 26 : 55 fhemtest . myds . me 1 2017 - 08 - 18 T21:26:55 fhemtest . myds . me Test_event 13339 FHEM - : 2017 - 08 - 18 21 : 26 : 55 USV state: OL
Aug 18 21 : 26 : 54 fhemtest . myds . me 1 2017 - 08 - 18 T21:26:54 fhemtest . myds . me Test_event 13339 FHEM - : 2017 - 08 - 18 21 : 26 : 54 Bezug state: done
Aug 18 21 : 26 : 54 fhemtest . myds . me 1 2017 - 08 - 18 T21:26:54 fhemtest . myds . me Test_event 13339 FHEM - : 2017 - 08 - 18 21 : 26 : 54 recalc_Bezug state: Next: 21 : 31 : 59
</pre>
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
2017-08-16 22:32:44 +00:00
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> addStateEvent </b> <br>
2017-08-16 22:32:44 +00:00
<br>
2018-08-01 19:20:56 +00:00
Das Attribut ist nur für "Sender" verwendbar . Wenn gesetzt , werden state - events mit dem Reading "state" ergänzt . <br/>
2017-08-16 22:32:44 +00:00
Die Standardeinstellung ist ohne state - Ergänzung .
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
<br>
2018-08-08 20:42:59 +00:00
<ul>
<li> <b> contDelimiter </b> <br>
<br>
Das Attribut ist nur für "Sender" verwendbar . Es enthält ein zusätzliches Zeichen welches unmittelber vor das
Content - Feld eingefügt wird . <br>
Diese Möglichkeit ist in manchen speziellen Fällen hilfreich ( z . B . kann das Zeichen ':' eingefügt werden um eine
ordnungsgemäße Anzeige im Synology - Protokollcenter zu erhalten ) .
</li>
</ul>
<br>
<br>
2017-08-16 22:32:44 +00:00
2018-08-05 19:04:41 +00:00
<ul>
2018-08-08 06:36:04 +00:00
<li> <b> disable [ 1 | 0 | maintenance ] </b> <br>
2017-08-18 19:51:33 +00:00
<br>
2018-08-08 20:42:59 +00:00
Das Device wird aktiviert , deaktiviert bzw . in den Maintenance - Mode geschaltet . Im Maintenance - Mode kann mit dem
"Sender" - Device eine Testnachricht gesendet werden ( siehe "set <name> sendTestMessage" ) .
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
<br>
2017-08-18 19:51:33 +00:00
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> logFormat [ BSD | IETF ] </b> <br>
2017-08-16 22:32:44 +00:00
<br>
2018-08-03 15:09:44 +00:00
Das Attribut ist nur für "Sender" verwendbar . Es stellt das Protokollformat ein . ( default: "IETF" ) <br>
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
<br>
2018-08-01 19:20:56 +00:00
2018-08-06 21:02:42 +00:00
<ul>
2018-08-13 21:55:35 +00:00
<li> <b> makeEvent [ intern | no | reading ] </b> <br>
2018-08-06 21:02:42 +00:00
<br>
Das Attribut ist nur für "Collector" verwendbar . Mit dem Attribut wird das Verhalten der Event - bzw .
Readinggenerierung festgelegt .
<br> <br>
<ul>
<table>
<colgroup> < col width = 10 % > < col width = 90 % > < / colgroup >
<tr> <td> <b> intern </b> </td> <td> es werden Events über die modulinterne Eventfunktion generiert </td> </tr>
<tr> <td> <b> no </b> </td> <td> es werden nur Readings der Form "MSG_<Hostname>" ohne Eventfunktion erstellt </td> </tr>
<tr> <td> <b> reading </b> </td> <td> es werden Readings der Form "MSG_<Hostname>" erstellt . Events werden in Abhängigkeit der "event-on-.*" - Attribute generiert </td> </tr>
</table>
</ul>
</li>
</ul>
<br>
<br>
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> outputFields </b> <br>
2018-08-01 19:20:56 +00:00
<br>
2018-08-08 20:42:59 +00:00
Über eine sortierbare Liste können die gewünschten Felder des generierten Events ausgewählt werden .
2018-08-05 19:04:41 +00:00
Die abhängig vom Attribut <b> "parseProfil" </b> sinnvoll verwendbaren Felder und deren Bedeutung ist der Beschreibung
des Attributs "parseProfil" zu entnehmen .
Ist "outputFields" nicht gesetzt , wird ein vordefinierter Satz Felder zur Eventgenerierung verwendet .
</li>
</ul>
<br>
<br>
<ul>
<li> <b> parseFn { & lt ; Parsefunktion & gt ; } </b> <br>
<br>
Das Attribut ist nur für Device - MODEL "Collector" verwendbar . Es wird die eingegebene Perl - Funktion auf die
empfangene Syslog - Meldung angewendet . Der Funktion werden folgende Variablen übergeben die zur Verarbeitung
und zur Werterückgabe genutzt werden können . Leer übergebene Variablen sind als "" gekennzeichnet . <br>
Das erwartete Rückgabeformat einer Variable wird in "()" angegeben sofern sie Restriktionen unterliegt .
Ansonsten ist die Variable frei verfügbar .
<br> <br>
<ul>
<table>
<colgroup> < col width = 20 % > < col width = 80 % > < / colgroup >
2018-08-06 20:07:30 +00:00
<tr> <td> $ PRIVAL </td> <td> "" ( 0 ... 191 ) </td> </tr>
<tr> <td> $ FAC </td> <td> "" ( 0 ... 23 ) </td> </tr>
<tr> <td> $ SEV </td> <td> "" ( 0 ... 7 ) </td> </tr>
2018-08-05 19:04:41 +00:00
<tr> <td> $ TS </td> <td> Zeitstempel ( YYYY - MM - DD hh:mm:ss ) </td> </tr>
<tr> <td> $ HOST </td> <td> "" </td> </tr>
<tr> <td> $ DATE </td> <td> "" ( YYYY - MM - DD ) </td> </tr>
<tr> <td> $ TIME </td> <td> "" ( hh:mm:ss ) </td> </tr>
<tr> <td> $ ID </td> <td> "" </td> </tr>
<tr> <td> $ PID </td> <td> "" </td> </tr>
<tr> <td> $ MID </td> <td> "" </td> </tr>
<tr> <td> $ SDFIELD </td> <td> "" </td> </tr>
<tr> <td> $ CONT </td> <td> "" </td> </tr>
<tr> <td> $ DATA </td> <td> übergebene Rohdaten der Syslog - Mitteilung ( keine Rückgabeauswertung ! ) </td> </tr>
</table>
</ul>
<br>
Die Variablennamen korrespondieren mit den Feldnamen und deren ursprünglicher Bedeutung angegeben im Attribut
2018-08-08 20:42:59 +00:00
<b> "parseProfile" </b> ( Erläuterung der Felddaten ) . <br> <br>
<ul>
<b> Beispiel: </b> <br>
# Quelltext: '<4> <;4>LAN IP and mask changed to 192.168.2.3 255.255.255.0' <br>
# Die Zeichen '<;4>' sollen aus dem CONT-Feld entfernt werden
<pre>
{
( $ PRIVAL , $ CONT ) = ( $ DATA =~ /^<(\d{1,3})>\s(.*)$/ ) ;
$ CONT = ( split ( ">" , $ CONT ) ) [ 1 ] if ( $ CONT =~ /^<.*>.*$/ ) ;
}
</pre>
</ul>
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
<br>
<ul>
2018-08-12 16:16:31 +00:00
<li> <b> parseProfile [ BSD | IETF | ... | ParseFn | raw ] </b> <br>
2018-08-05 19:04:41 +00:00
<br>
Auswahl eines Parsing - Profiles . Das Attribut ist nur für Device - MODEL "Collector" verwendbar .
<br> <br>
<ul>
<table>
<colgroup> < col width = 20 % > < col width = 80 % > < / colgroup >
<tr> <td> <b> BSD </b> </td> <td> Parsing der Meldungen im BSD - Format nach RFC3164 </td> </tr>
<tr> <td> <b> IETF </b> </td> <td> Parsing der Meldungen im IETF - Format nach RFC5424 ( default ) </td> </tr>
2018-08-12 16:16:31 +00:00
<tr> <td> <b> ... </b> </td> <td> Es werden weitere angepasste Parsingprofile für ausgewählte Geräte angeboten </td> </tr>
2018-08-05 19:04:41 +00:00
<tr> <td> <b> ParseFn </b> </td> <td> Verwendung einer eigenen spezifischen Parsingfunktion im Attribut "parseFn" . </td> </tr>
<tr> <td> <b> raw </b> </td> <td> kein Parsing , die Meldungen werden wie empfangen in ein Event umgesetzt </td> </tr>
</table>
</ul>
<br>
Die geparsten Informationen werden in Feldern zur Verfügung gestellt . Die im Event erscheinenden Felder und deren
Reihenfolge können mit dem Attribut <b> "outputFields" </b> bestimmt werden . <br>
Abhängig vom verwendeten "parseProfile" werden die folgenden Felder mit Werten gefüllt und es ist dementsprechend auch
nur sinnvoll die benannten Felder in Attribut "outputFields" zu verwenden . Im raw - Profil werden die empfangenen Daten
ohne Parsing in ein Event umgewandelt .
<br> <br>
Die sinnvoll im Attribut "outputFields" verwendbaren Felder des jeweilgen Profils sind:
<br>
<br>
<ul>
<table>
2018-08-08 20:42:59 +00:00
<colgroup> < col width = 10 % > < col width = 90 % > < / colgroup >
<tr> <td> BSD </td> <td> - > PRIVAL , FAC , SEV , TS , HOST , ID , CONT </td> </tr>
<tr> <td> IETF </td> <td> - > PRIVAL , FAC , SEV , TS , HOST , DATE , TIME , ID , PID , MID , SDFIELD , CONT </td> </tr>
<tr> <td> ParseFn </td> <td> - > PRIVAL , FAC , SEV , TS , HOST , DATE , TIME , ID , PID , MID , SDFIELD , CONT </td> </tr>
<tr> <td> raw </td> <td> - > keine Auswahl sinnvoll , es wird immer die Originalmeldung in einen Event umgesetzt </td> </tr>
2018-08-05 19:04:41 +00:00
</table>
</ul>
<br>
Erläuterung der Felddaten:
<br>
<br>
<ul>
<table>
<colgroup> < col width = 20 % > < col width = 80 % > < / colgroup >
<tr> <td> PRIVAL </td> <td> kodierter Priority Wert ( kodiert aus "facility" und "severity" ) </td> </tr>
<tr> <td> FAC </td> <td> Kategorie ( Facility ) </td> </tr>
<tr> <td> SEV </td> <td> Schweregrad der Meldung ( Severity ) </td> </tr>
<tr> <td> TS </td> <td> Zeitstempel aus Datum und Zeit ( YYYY - MM - DD hh:mm:ss ) </td> </tr>
<tr> <td> HOST </td> <td> Hostname / Ip-Adresse des Senders </ td > </tr>
<tr> <td> DATE </td> <td> Datum ( YYYY - MM - DD ) </td> </tr>
<tr> <td> TIME </td> <td> Zeit ( hh:mm:ss ) </td> </tr>
<tr> <td> ID </td> <td> Gerät oder Applikation welche die Meldung gesendet hat </td> </tr>
<tr> <td> PID </td> <td> Programm - ID , oft belegt durch Prozessname bzw . Prozess - ID </td> </tr>
<tr> <td> MID </td> <td> Typ der Mitteilung ( beliebiger String ) </td> </tr>
<tr> <td> SDFIELD </td> <td> Metadaten über die empfangene Syslog - Mitteilung </td> </tr>
<tr> <td> CONT </td> <td> Inhalt der Meldung </td> </tr>
<tr> <td> DATA </td> <td> empfangene Rohdaten </td> </tr>
</table>
</ul>
<br>
</li>
</ul>
<br>
2017-08-16 22:32:44 +00:00
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> protocol [ TCP | UDP ] </b> <br>
2017-08-16 22:32:44 +00:00
<br>
2018-08-01 19:20:56 +00:00
Setzt den Protokolltyp der verwendet werden soll . Es kann UDP oder TCP gewählt werden ( MODEL Sender ) . <br>
2017-08-16 22:32:44 +00:00
Standard ist "UDP" wenn nichts spezifiziert ist .
2018-08-01 19:20:56 +00:00
Ein Syslog - Server ( MODEL Collector ) verwendet UDP .
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
2017-08-16 22:32:44 +00:00
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> port & lt ; Port & gt ; </b> <br>
2017-08-16 22:32:44 +00:00
<br>
2018-08-05 19:04:41 +00:00
Der verwendete Port . Für einen Sender ist der default - Port 514 , für einen Collector ( Syslog - Server ) der Port 1514 .
</li>
</ul>
<br>
<br>
2017-08-16 22:32:44 +00:00
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> rateCalcRerun & lt ; Zeit in Sekunden & gt ; </b> <br>
2017-08-27 10:11:05 +00:00
<br>
2018-08-05 19:04:41 +00:00
Wiederholungszyklus für die Bestimmung der Log - Transferrate ( Reading "Transfered_logs_per_minute" ) in Sekunden ( >= 60 ) .
Eingegebene Werte < 60 Sekunden werden automatisch auf 60 Sekunden korrigiert .
2017-08-27 10:11:05 +00:00
Default sind 60 Sekunden .
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
<br>
2018-08-01 19:20:56 +00:00
2018-08-08 20:42:59 +00:00
<ul>
2018-08-13 21:55:35 +00:00
<li> <b> respectSeverity </b> <br>
2018-08-08 20:42:59 +00:00
<br>
2018-08-13 21:55:35 +00:00
Es werden nur Nachrichten übermittelt ( Sender ) bzw . beim Empfang berücksichtigt ( Collector ) , deren Schweregrad im
Attribut enthalten ist .
Ist "respectSeverity" nicht gesetzt , werden Nachrichten aller Schweregrade verarbeitet .
2018-08-08 20:42:59 +00:00
</li>
</ul>
<br>
<br>
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> ssldebug </b> <br>
2018-08-01 19:20:56 +00:00
<br>
Debugging Level von SSL Messages . <br> <br>
<ul>
<li> 0 - Kein Debugging ( default ) . </li>
<li> 1 - Ausgabe Errors von from < a href = "http://search.cpan.org/~sullr/IO-Socket-SSL-2.056/lib/IO/Socket/SSL.pod" > IO::Socket:: SSL </a> und ciphers von < a href = "http://search.cpan.org/~mikem/Net-SSLeay-1.85/lib/Net/SSLeay.pod" > Net:: SSLeay </a> . </li>
<li> 2 - zusätzliche Ausgabe von Informationen über den Protokollfluss von < a href = "http://search.cpan.org/~sullr/IO-Socket-SSL-2.056/lib/IO/Socket/SSL.pod" > IO::Socket:: SSL </a> und Fortschritinformationen von < a href = "http://search.cpan.org/~mikem/Net-SSLeay-1.85/lib/Net/SSLeay.pod" > Net:: SSLeay </a> . </li>
<li> 3 - zusätzliche Ausgabe einiger Dumps von < a href = "http://search.cpan.org/~sullr/IO-Socket-SSL-2.056/lib/IO/Socket/SSL.pod" > IO::Socket:: SSL </a> und < a href = "http://search.cpan.org/~mikem/Net-SSLeay-1.85/lib/Net/SSLeay.pod" > Net:: SSLeay </a> . </li>
</ul>
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
<br>
2017-08-27 10:11:05 +00:00
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> TLS </b> <br>
2018-08-01 19:20:56 +00:00
<br>
Das Attribut ist nur für "Sender" verwendbar .
Es wird eine gesicherte Verbindung zum Syslog - Server aufgebaut . Das Protokoll schaltet automatisch
auf TCP um .
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
<br>
2018-08-01 19:20:56 +00:00
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> timeout </b> <br>
2017-08-25 08:28:14 +00:00
<br>
2018-08-01 19:20:56 +00:00
Das Attribut ist nur für "Sender" verwendbar .
Timeout für die Verbindung zum Syslog - Server ( TCP ) . Default: 0.5 s .
2018-08-05 19:04:41 +00:00
</li>
</ul>
<br>
<br>
2017-08-25 08:28:14 +00:00
2018-08-05 19:04:41 +00:00
<ul>
<li> <b> verbose </b> <br>
2017-08-22 06:41:25 +00:00
<br>
Die Ausgaben der Verbose - Level von Log2Syslog - Devices werden ausschließlich im lokalen FHEM Logfile ausgegeben und
nicht weitergeleitet um Schleifen zu vermeiden .
2018-08-05 19:04:41 +00:00
</li>
</ul>
2017-08-27 10:38:38 +00:00
<br>
2018-08-05 19:04:41 +00:00
<br>
</ul>
<br>
2017-08-27 10:38:38 +00:00
< a name = "Log2Syslogreadings" > </a>
<b> Readings </b>
<ul>
<br>
<table>
<colgroup> < col width = 35 % > < col width = 65 % > < / colgroup >
2018-08-06 21:28:05 +00:00
<tr> <td> <b> MSG_ & lt ; Host & gt ; </b> </td> <td> die letzte erfolgreich geparste Syslog - Message von & lt ; Host & gt ; </td> </tr>
2017-08-27 10:38:38 +00:00
<tr> <td> <b> SSL_Algorithm </b> </td> <td> der verwendete SSL Algorithmus wenn SSL eingeschaltet und aktiv ist </td> </tr>
2018-08-01 19:20:56 +00:00
<tr> <td> <b> SSL_Version </b> </td> <td> die verwendete TLS - Version wenn die Verschlüsselung aktiv ist </td> </tr>
<tr> <td> <b> Transfered_logs_per_minute </b> </td> <td> die durchschnittliche Anzahl der übertragenen /empfangenen Logs/ Events pro Minute </td> </tr>
2017-08-27 10:38:38 +00:00
</table>
<br>
</ul>
2017-08-16 22:32:44 +00:00
</ul>
= end html_DE
2017-08-25 08:28:14 +00:00
= cut