| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293 |
- ##########################################################################################################################
- # $Id: 93_Log2Syslog.pm 17636 2018-10-28 16:49:17Z DS_Starter $
- ##########################################################################################################################
- # 93_Log2Syslog.pm
- #
- # (c) 2017-2018 by Heiko Maaz
- # 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/>.
- #
- # The module is based on idea and input from betateilchen 92_rsyslog.pm
- #
- # Implements the Syslog Protocol of RFC 5424 https://tools.ietf.org/html/rfc5424
- # and RFC 3164 https://tools.ietf.org/html/rfc3164 and
- # TLS Transport according to RFC5425 https://tools.ietf.org/pdf/rfc5425.pdf as well
- #
- ##########################################################################################################################
- package main;
- use strict;
- use warnings;
- use TcpServerUtils;
- use Scalar::Util qw(looks_like_number);
- use Encode qw(encode_utf8);
- eval "use IO::Socket::INET;1" or my $MissModulSocket = "IO::Socket::INET";
- eval "use Net::Domain qw(hostname hostfqdn hostdomain domainname);1" or my $MissModulNDom = "Net::Domain";
- # Versions History intern:
- our %Log2Syslog_vNotesIntern = (
- "5.3.1" => "21.10.2018 get of FQDN changed ",
- "5.3.0" => "16.10.2018 attribute sslCertPrefix added (Forum:#92030), module hints & release info order switched ",
- "5.2.1" => "08.10.2018 setpayload of BSD-format changed, commandref revised ",
- "5.2.0" => "02.10.2018 added direct help for attributes",
- "5.1.0" => "01.10.2018 new get <name> versionNotes command",
- "5.0.1" => "27.09.2018 Log2Syslog_closesock if write error:.* , delete readings code changed",
- "5.0.0" => "26.09.2018 TCP-Server in Collector-mode, HIPCACHE added, PROFILE as Internal, Parse_Err_No as reading,
- octetCount attribute, TCP-SSL-support, set 'reopen' command, code fixes",
- "4.8.5" => "20.08.2018 BSD/parseFn parsing changed, BSD setpayload changed, new variable \$IGNORE in parseFn",
- "4.8.4" => "15.08.2018 BSD parsing changed",
- "4.8.3" => "14.08.2018 BSD setpayload changed, BSD parsing changed, Internal MYFQDN",
- "4.8.2" => "13.08.2018 rename makeMsgEvent to makeEvent",
- "4.8.1" => "12.08.2018 IETF-Syslog without VERSION changed, Log verbose 1 to 2 changed in parsePayload",
- "4.8.0" => "12.08.2018 enhanced IETF Parser to match logs without version",
- "4.7.0" => "10.08.2018 Parser for TPLink",
- "4.6.1" => "10.08.2018 some perl warnings, changed IETF Parser",
- "4.6.0" => "08.08.2018 set sendTestMessage added, Attribute 'contDelimiter', 'respectSeverity'",
- "4.5.1" => "07.08.2018 BSD Regex changed, setpayload of BSD changed",
- "4.5.0" => "06.08.2018 Regex capture groups used in parsePayload to set variables, parsing of BSD changed,
- Attribute 'makeMsgEvent' added",
- "4.4.0" => "04.08.2018 Attribute 'outputFields' added",
- "4.3.0" => "03.08.2018 Attribute 'parseFn' added",
- "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)",
- "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",
- "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
- rateCalcRerun, function Log2Syslog_closesock",
- "2.5.1" => "24.08.2017 some fixes",
- "2.5.0" => "23.08.2017 TLS encryption available, new readings, \$readingFnAttributes",
- "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",
- "2.3.1" => "19.08.2017 commandref revised",
- "2.3.0" => "18.08.2017 new parameter 'ident' in DEF, sub setidex, Log2Syslog_charfilter",
- "2.2.0" => "17.08.2017 set BSD data length, set only acceptable characters (USASCII) in payload,
- commandref revised",
- "2.1.0" => "17.08.2017 sub Log2Syslog_opensock created",
- "2.0.0" => "16.08.2017 create syslog without SYS::SYSLOG",
- "1.1.1" => "13.08.2017 registrate Log2Syslog_fhemlog to %loginform in case of sending fhem-log
- attribute timeout, commandref revised",
- "1.1.0" => "26.07.2017 add regex search to sub Log2Syslog_fhemlog",
- "1.0.0" => "25.07.2017 initial version"
- );
- # Versions History extern:
- our %Log2Syslog_vNotesExtern = (
- "5.3.0" => "16.10.2018 attribute sslCertPrefix added to support multiple SSL-keys (Forum:#92030)",
- "5.2.1" => "08.10.2018 Send format of BSD changed. The TAG-field was changed to \"IDENT[PID]: \" ",
- "5.2.0" => "02.10.2018 direct help for attributes added",
- "5.1.0" => "29.09.2018 new get <name> versionNotes command ",
- "5.0.1" => "27.09.2018 automatic reconnect to syslog-server in case of write error ",
- "5.0.0" => "26.09.2018 <li>TCP Server mode is possible now for Collector devices<\li><li>the used parse-profile is shown as Internal<\li><li>Parse_Err_No counts faulty persings since start<\li><li>new octetCount attribute switches the syslog framing method (see also RFC6587 <a href=\"https://tools.ietf.org/html/rfc6587\">Transmission of Syslog Messages over TCP</a>)<\li><li>TCP SSL-support<\li><li>new set 'reopen' command to reconnect a broken connection<\li><li>some code fixes ",
- "4.8.5" => "20.08.2018 BSD/parseFn parse changed, BSD setpayload changed, new variable \$IGNORE in parseFn ",
- "4.8.4" => "15.08.2018 BSD parse changed again ",
- "4.8.3" => "14.08.2018 BSD setpayload changed, BSD parse changed, new Internal MYFQDN ",
- "4.8.2" => "13.08.2018 rename makeMsgEvent to makeEvent ",
- "4.8.1" => "12.08.2018 IETF-Syslog without VERSION changed, Log verbose 1 to 2 changed in parsePayload ",
- "4.8.0" => "12.08.2018 enhanced IETF Parser to match logs without version ",
- "4.7.0" => "10.08.2018 Parser for TPLink added ",
- "4.6.1" => "10.08.2018 fix some perl warnings, changed IETF Parser ",
- "4.6.0" => "08.08.2018 set sendTestMessage added, new attributes 'contDelimiter', 'respectSeverity' ",
- "4.5.1" => "07.08.2018 BSD Regex changed, setpayload of BSD changed ",
- "4.5.0" => "06.08.2018 parsing of BSD changed, attribute 'makeMsgEvent' added ",
- "4.4.0" => "04.08.2018 Attribute 'outputFields' added ",
- "4.3.0" => "03.08.2018 Attribute 'parseFn' added ",
- "4.2.0" => "03.08.2018 evaluate sender peer ip-address/hostname and 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) implemented ",
- "3.2.1" => "04.05.2018 fix compatibility with newer IO::Socket::SSL on debian 9, attribute 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 ",
- "3.0.0" => "27.08.2017 change attr type to protocol, ready to first check in ",
- "2.6.0" => "26.08.2017 more than one Log2Syslog device can be created ",
- "2.5.2" => "26.08.2018 attribute rateCalcRerun ",
- "2.5.1" => "24.08.2017 some bugfixes ",
- "2.5.0" => "23.08.2017 TLS encryption available to Sender ",
- "2.4.1" => "21.08.2017 change PROCID to \$hash->{SEQNO}, switch to non-blocking in subs event/fhemlog ",
- "2.4.0" => "20.08.2017 new sub for entries in local fhemlog only including verbose support ",
- "2.3.1" => "19.08.2017 commandref revised ",
- "2.3.0" => "18.08.2017 new parameter 'ident' in Define to indentify sylog source ",
- "2.2.0" => "17.08.2017 set BSD data length, set only acceptable characters (USASCII) in payload ",
- "2.0.0" => "16.08.2017 create syslog without perl module SYS::SYSLOG ",
- "1.1.0" => "26.07.2017 add regex search to sub Log2Syslog_fhemlog ",
- "1.0.0" => "25.07.2017 initial version "
- );
- # Hint Hash
- our %Log2Syslog_vHintsExt = (
- "3" => "The <a href=\"https://tools.ietf.org/pdf/rfc5425.pdf\">RFC5425</a> TLS Transport Protocol",
- "2" => "The basics of <a href=\"https://tools.ietf.org/html/rfc3164\">RFC3164 (BSD)</a> protocol",
- "1" => "Informations about <a href=\"https://tools.ietf.org/html/rfc5424\">RFC5424 (IETF)</a> syslog protocol"
- );
- # Mappinghash BSD-Formatierung Monat
- our %Log2Syslog_BSDMonth = (
- "01" => "Jan",
- "02" => "Feb",
- "03" => "Mar",
- "04" => "Apr",
- "05" => "May",
- "06" => "Jun",
- "07" => "Jul",
- "08" => "Aug",
- "09" => "Sep",
- "10" => "Oct",
- "11" => "Nov",
- "12" => "Dec",
- "Jan" => "01",
- "Feb" => "02",
- "Mar" => "03",
- "Apr" => "04",
- "May" => "05",
- "Jun" => "06",
- "Jul" => "07",
- "Aug" => "08",
- "Sep" => "09",
- "Oct" => "10",
- "Nov" => "11",
- "Dec" => "12"
- );
- # Mappinghash Severity
- my %Log2Syslog_Severity = (
- "0" => "Emergency",
- "1" => "Alert",
- "2" => "Critical",
- "3" => "Error",
- "4" => "Warning",
- "5" => "Notice",
- "6" => "Informational",
- "7" => "Debug",
- "Emergency" => "0",
- "Alert" => "1",
- "Critical" => "2",
- "Error" => "3",
- "Warning" => "4",
- "Notice" => "5",
- "Informational" => "6",
- "Debug" => "7"
- );
- # 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",
- "23" => "local7"
- );
- # Längenvorgaben nach RFC3164
- my %RFC3164len = ("TAG" => 32, # max. Länge TAG-Feld
- "DL" => 1024 # max. Lange Message insgesamt
- );
-
- # Längenvorgaben nach RFC5425
- 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
- );
-
- ###############################################################################
- # Forward declarations
- #
- sub Log2Syslog_Log3slog($$$);
- ###############################################################################
- sub Log2Syslog_Initialize($) {
- my ($hash) = @_;
- $hash->{DefFn} = "Log2Syslog_Define";
- $hash->{UndefFn} = "Log2Syslog_Undef";
- $hash->{DeleteFn} = "Log2Syslog_Delete";
- $hash->{SetFn} = "Log2Syslog_Set";
- $hash->{GetFn} = "Log2Syslog_Get";
- $hash->{AttrFn} = "Log2Syslog_Attr";
- $hash->{NotifyFn} = "Log2Syslog_eventlog";
- $hash->{ReadFn} = "Log2Syslog_Read";
- $hash->{AttrList} = "addStateEvent:1,0 ".
- "disable:1,0,maintenance ".
- "addTimestamp:0,1 ".
- "contDelimiter ".
- "logFormat:BSD,IETF ".
- "makeEvent:no,intern,reading ".
- "outputFields:sortable-strict,PRIVAL,FAC,SEV,TS,HOST,DATE,TIME,ID,PID,MID,SDFIELD,CONT ".
- "parseProfile:BSD,IETF,TPLink-Switch,raw,ParseFn ".
- "parseFn:textField-long ".
- "respectSeverity:multiple-strict,Emergency,Alert,Critical,Error,Warning,Notice,Informational,Debug ".
- "octetCount:1,0 ".
- "ssldebug:0,1,2,3 ".
- "sslCertPrefix ".
- "TLS:1,0 ".
- "timeout ".
- "protocol:UDP,TCP ".
- "port ".
- "rateCalcRerun ".
- $readingFnAttributes
- ;
- return undef;
- }
- ###############################################################################
- sub Log2Syslog_Define($@) {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- my $name = $hash->{NAME};
-
- 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);
-
- # Example Sender: define splunklog Log2Syslog splunk.myds.me ident:Prod event:.* fhem:.*
- # Example Collector: define SyslogServer Log2Syslog
-
- delete($hash->{HELPER}{EVNTLOG});
- delete($hash->{HELPER}{FHEMLOG});
- delete($hash->{HELPER}{IDENT});
-
- $hash->{MYHOST} = hostname(); # eigener Host (lt. RFC nur Hostname f. BSD)
- my $myfqdn = hostfqdn(); # MYFQDN eigener Host (f. IETF)
- $hash->{MYFQDN} = $myfqdn?$myfqdn:$hash->{MYHOST};
-
- if(int(@a)-3 < 0){
- # Einrichtung Servermode (Collector)
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - entering Syslog servermode ...");
- $hash->{MODEL} = "Collector";
- $hash->{PROFILE} = "IETF";
- readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
- 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});
-
- $hash->{PEERHOST} = $a[2]; # Destination Host (Syslog Server)
- }
- $hash->{SEQNO} = 1; # PROCID in IETF, wird kontinuierlich hochgezählt
- $hash->{VERSION} = (reverse sort(keys %Log2Syslog_vNotesIntern))[0];
- $logInform{$hash->{NAME}} = "Log2Syslog_fhemlog"; # Funktion die in hash %loginform für $name eingetragen wird
- $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
- $hash->{HELPER}{OLDSTATE} = "initialized";
-
- readingsBeginUpdate($hash);
- readingsBulkUpdate($hash, "SSL_Version", "n.a.");
- readingsBulkUpdate($hash, "SSL_Algorithm", "n.a.");
- readingsBulkUpdate($hash, "Transfered_logs_per_minute", 0);
- readingsBulkUpdate($hash, "state", "initialized") if($hash->{MODEL}=~/Sender/);
- readingsEndUpdate($hash,1);
-
- Log2Syslog_trate($hash); # regelm. Berechnung Transfer Rate starten
-
- return undef;
- }
- #################################################################################################
- # Syslog Collector (Server-Mode) initialisieren
- # (im Collector Model)
- #################################################################################################
- sub Log2Syslog_initServer($) {
- my ($a) = @_;
- my ($name,$global) = split(",",$a);
- my $hash = $defs{$name};
- my $err;
- RemoveInternalTimer($hash, "Log2Syslog_initServer");
- return if(IsDisabled($name) || $hash->{SERVERSOCKET});
-
- if($init_done != 1 || Log2Syslog_IsMemLock($hash)) {
- InternalTimer(gettimeofday()+1, "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"));
-
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Opening socket on interface \"$global\" ...");
-
- if($protocol =~ /udp/) {
- $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}) {
- $err = "Can't open Syslog Collector at $port: $!";
- Log2Syslog_Log3slog ($hash, 1, "Log2Syslog $name - $err");
- readingsSingleUpdate ($hash, 'state', $err, 1);
- return;
- }
- $hash->{FD} = $hash->{SERVERSOCKET}->fileno();
- $hash->{PORT} = $hash->{SERVERSOCKET}->sockport();
- } else {
- $lh = "global" if(!$lh);
- my $ret = TcpServer_Open($hash,$port,$lh);
- if($ret) {
- $err = "Can't open Syslog TCP Collector at $port: $ret";
- Log2Syslog_Log3slog ($hash, 1, "Log2Syslog $name - $err");
- readingsSingleUpdate ($hash, 'state', $err, 1);
- return;
- }
- }
-
- $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";
-
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - port $hash->{PORT}/$protocol opened for Syslog Collector on interface \"$hash->{INTERFACE}\"");
- readingsSingleUpdate ($hash, "state", "initialized", 1);
- delete($readyfnlist{"$name.$port"});
- $selectlist{"$name.$port"} = $hash;
- return;
- }
- ########################################################################################################
- # Syslog Collector Daten empfangen (im Collector-Mode)
- #
- # !!!!! Achtung !!!!!
- # Kontextswitch des $hash beachten: initialer TCP-Server <-> temporärer TCP-Server ohne SERVERSOCKET
- #
- ########################################################################################################
- # called from the global loop, when the select for hash->{FD} reports data
- sub Log2Syslog_Read($@) {
- my ($hash,$reread) = @_;
- my $socket = $hash->{SERVERSOCKET};
- my ($err,$sev,$data,$ts,$phost,$pl,$ignore,$st,$len,$evt,$pen);
-
- return if($init_done != 1);
-
- my $mlen = 8192; # maximale Länge des Syslog-Frames als Begrenzung falls kein EOF
- # vom Sender initiiert wird (Endlosschleife vermeiden)
- if($hash->{TEMPORARY}) {
- # temporäre Instanz angelegt durch TcpServer_Accept
- $len = 8192;
- ($st,$data,$hash) = Log2Syslog_getifdata($hash,$len,$mlen,$reread);
- }
-
- my $name = $hash->{NAME};
- return if(IsDisabled($name) || Log2Syslog_IsMemLock($hash));
- my $pp = AttrVal($name, "parseProfile", "IETF");
- my $mevt = AttrVal($name, "makeEvent", "intern"); # wie soll Reading/Event erstellt werden
- my $sevevt = AttrVal($name, "respectSeverity", ""); # welcher Schweregrad soll berücksichtigt werden (default: alle)
-
- if($pp =~ /BSD/) {
- # BSD-Format
- $len = $RFC3164len{DL};
-
- } elsif ($pp =~ /IETF/) {
- # IETF-Format
- $len = $RFC5425len{DL};
-
- } else {
- # raw oder User eigenes Format
- $len = 8192;
- }
-
- if($socket) {
- ($st,$data,$hash) = Log2Syslog_getifdata($hash,$len,$mlen,$reread);
- }
-
- if($data) {
- # parse Payload
- my (@load,$mlen,$msg,$tail);
- if($data =~ /^(?<mlen>(\d+))\s(?<tail>.*)/s) {
- # Syslog Sätze mit Octet Count -> Transmission of Syslog Messages over TCP https://tools.ietf.org/html/rfc6587
- my $i = 0;
- $mlen = $+{mlen};
- $tail = $+{tail};
- $msg = substr($tail,0,$mlen);
- chomp $msg;
- push @load, $msg;
- $tail = substr($tail,$mlen);
- Log2Syslog_Log3slog ($hash, 5, "Log2Syslog $name -> LEN$i: $mlen, MSG$i: $msg, TAIL$i: $tail");
-
- while($tail && $tail =~ /^(?<mlen>(\d+))\s(?<tail>.*)/s) {
- $i++;
- $mlen = $+{mlen};
- $tail = $+{tail};
- $msg = substr($tail,0,$mlen);
- chomp $msg;
- push @load, $msg;
- $tail = substr($tail,$mlen);
- Log2Syslog_Log3slog ($hash, 5, "Log2Syslog $name -> LEN$i: $mlen, MSG$i: $msg, TAIL$i: $tail");
- }
- } else {
- @load = split("[\r\n]",$data);
- }
-
- foreach my $line (@load) {
- ($err,$ignore,$sev,$phost,$ts,$pl) = Log2Syslog_parsePayload($hash,$line);
- $hash->{SEQNO}++;
- if($err) {
- $pen = ReadingsVal($name, "Parse_Err_No", 0);
- $pen++;
- readingsSingleUpdate($hash, 'Parse_Err_No', $pen, 1);
- $st = "parse error - see logfile";
- } elsif ($ignore) {
- Log2Syslog_Log3slog ($hash, 5, "Log2Syslog $name -> dataset was ignored by parseFn");
- } else {
- return if($sevevt && $sevevt !~ m/$sev/); # Message nicht berücksichtigen
- $st = "active";
- 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);
- }
- }
- $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
- readingsSingleUpdate($hash, "state", $st, $evt);
- $hash->{HELPER}{OLDSTATE} = $st;
- }
- }
-
- return;
- }
- ###############################################################################
- # Daten vom Interface holen
- #
- # Die einzige Aufgabe der Instanz mit SERVERSOCKET ist TcpServer_Accept
- # durchzufuehren (und evtl. noch Statistiken). Durch den Accept wird eine
- # weitere Instanz des gleichen Typs angelegt die eine Verbindung repraesentiert
- # und im ReadFn die eigentliche Arbeit macht:
- #
- # - ohne SERVERSOCKET dafuer mit CD/FD, PEER und PORT. CD/FD enthaelt den
- # neuen Filedeskriptor.
- # - mit TEMPORARY (damit es nicht gespeichert wird)
- # - SNAME verweist auf die "richtige" Instanz, damit man die Attribute
- # abfragen kann.
- # - TcpServer_Accept traegt den neuen Filedeskriptor in die globale %selectlist
- # ein. Damit wird ReadFn von fhem.pl/select mit dem temporaeren Instanzhash
- # aufgerufen, wenn Daten genau bei dieser Verbindung anstehen.
- # (sSiehe auch "list TYPE=FHEMWEB", bzw. "man -s2 accept")
- #
- ###############################################################################
- sub Log2Syslog_getifdata($$@) {
- my ($hash,$len,$mlen,$reread) = @_;
- my $name = $hash->{NAME};
- my $socket = $hash->{SERVERSOCKET};
- my $protocol = lc(AttrVal($name, "protocol", "udp"));
- if($hash->{TEMPORARY}) {
- # temporäre Instanz abgelegt durch TcpServer_Accept
- $protocol = "tcp";
- }
- my $st = ReadingsVal($name,"state","active");
- my ($data,$ret);
-
- if($socket && $protocol =~ /udp/) {
- # UDP Datagramm empfangen
- Log2Syslog_Log3slog ($hash, 4, "Log2Syslog $name - ####################################################### ");
- Log2Syslog_Log3slog ($hash, 4, "Log2Syslog $name - ######### new Syslog UDP Parsing ######### ");
- Log2Syslog_Log3slog ($hash, 4, "Log2Syslog $name - ####################################################### ");
- unless($socket->recv($data, $len)) {
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Seq \"$hash->{SEQNO}\" invalid data: $data");
- $data = '' if(length($data) == 0);
- $st = "receive error - see logfile";
- }
- } elsif ($protocol =~ /tcp/) {
- if($hash->{SERVERSOCKET}) { # Accept and create a child
- my $nhash = TcpServer_Accept($hash, "Log2Syslog");
- return ($st,$data,$hash) if(!$nhash);
- $nhash->{CD}->blocking(0);
- if($nhash->{SSL}) {
- my $sslver = $nhash->{CD}->get_sslversion();
- my $sslalgo = $nhash->{CD}->get_fingerprint();
- readingsSingleUpdate($hash, "SSL_Version", $sslver, 1);
- readingsSingleUpdate($hash, "SSL_Algorithm", $sslalgo, 1);
- }
- return ($st,$data,$hash);
- }
- my $sname = $hash->{SNAME};
- my $cname = $hash->{NAME};
- my $shash = $defs{$sname}; # Hash des Log2Syslog-Devices bei temporärer TCP-Serverinstanz
-
- Log2Syslog_Log3slog ($shash, 4, "Log2Syslog $sname - ####################################################### ");
- Log2Syslog_Log3slog ($shash, 4, "Log2Syslog $sname - ######### new Syslog TCP Parsing ######### ");
- Log2Syslog_Log3slog ($shash, 4, "Log2Syslog $sname - ####################################################### ");
- Log2Syslog_Log3slog ($shash, 4, "Log2Syslog $sname - childname: $cname");
- $st = ReadingsVal($sname,"state","active");
- my $c = $hash->{CD};
- if($c) {
- $shash->{HELPER}{TCPPADDR} = $hash->{PEER};
- if(!$reread) {
- my $buf;
- my $off = 0;
- $ret = sysread($c, $buf, $len); # returns undef on error, 0 at end of file and Integer, number of bytes read on success.
-
- if(!defined($ret) && $! == EWOULDBLOCK ){
- # error
- $hash->{wantWrite} = 1 if(TcpServer_WantWrite($hash));
- $hash = $shash;
- return ($st,undef,$hash);
- } elsif (!$ret) {
- # end of file
- CommandDelete(undef, $cname);
- $hash = $shash;
- Log2Syslog_Log3slog ($shash, 4, "Log2Syslog $sname - Connection closed for $cname: ".(defined($ret) ? 'EOF' : $!));
- return ($st,undef,$hash);
-
- }
- $hash->{BUF} .= $buf;
-
- if($hash->{SSL} && $c->can('pending')) {
- while($c->pending()) {
- sysread($c, $buf, 1024);
- $hash->{BUF} .= $buf;
- }
- }
-
- $data = $hash->{BUF};
- delete $hash->{BUF};
- $hash = $shash;
- Log2Syslog_Log3slog ($shash, 5, "Log2Syslog $sname - Buffer content:\n$data");
- }
- }
-
- } else {
- $st = "error - no socket opened";
- $data = '';
- }
- return ($st,$data,$hash);
- }
- ###############################################################################
- # Parsen Payload für Syslog-Server
- # (im Collector Model)
- ###############################################################################
- sub Log2Syslog_parsePayload($$) {
- my ($hash,$data) = @_;
- my $name = $hash->{NAME};
- 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
- my $ignore = 0;
- my ($Mmm,$dd,$delimiter,$day,$ietf,$err,$pl,$tail);
-
- # Hash zur Umwandlung Felder in deren Variablen
- my ($prival,$ts,$host,$date,$time,$id,$pid,$mid,$sdfield,$cont);
- my $fac = "";
- my $sev = "";
- 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
- );
-
- # Sender Host / IP-Adresse ermitteln, $phost wird Reading im Event
- my ($phost) = Log2Syslog_evalPeer($hash);
-
- Log2Syslog_Log3slog ($hash, 4, "Log2Syslog $name - raw message -> $data");
-
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); # Istzeit Ableitung
- $year = $year+1900;
-
- if ($pp =~ /raw/) {
- Log2Syslog_Log3slog($name, 4, "$name - $data");
- $ts = TimeNow();
- $pl = $data;
-
- } elsif ($pp eq "BSD") {
- # BSD Protokollformat https://tools.ietf.org/html/rfc3164
- # Beispiel data "<$prival>$month $day $time $myhost $id: $otp"
- $data =~ /^<(?<prival>\d{1,3})>(?<tail>.*)$/;
- $prival = $+{prival}; # must
- $tail = $+{tail};
- $tail =~ /^((?<month>\w{3})\s+(?<day>\d{1,2})\s+(?<time>\d{2}:\d{2}:\d{2}))?\s+(?<tail>.*)$/;
- $Mmm = $+{month}; # should
- $dd = $+{day}; # should
- $time = $+{time}; # should
- $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
- $tail =~ /^(?<host>[^\s]*)?\s(?<tail>.*)$/;
- $host = $+{host}; # should
- $tail = $+{tail};
- $tail =~ /^(?<id>(\w*))?(?<cont>(\[\w*\]:|:\s).*)$/;
- $id = $+{id}; # should
- if($id) {
- $id = substr($id,0, ($RFC3164len{TAG}-1)); # Länge TAG-Feld nach RFC begrenzen
- $cont = $+{cont}; # should
- } else {
- $cont = $tail;
- }
- } else {
- # andernfalls eher kein Standardaufbau
- $cont = $tail;
- }
- if(!$prival) {
- $err = 1;
- Log2Syslog_Log3slog ($hash, 2, "Log2Syslog $name - error parse msg -> $data");
- } else {
- $cont =~ s/^(:\s*)(.*)$/$2/;
- 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");
- }
-
- no warnings 'uninitialized';
- 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");
- $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++;
- }
- }
- }
-
- } elsif ($pp eq "IETF") {
- # IETF Protokollformat https://tools.ietf.org/html/rfc5424
- # 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>.*)$/;
- $prival = $+{prival}; # must
- $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
- $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>.*)$/;
- $prival = $+{prival}; # must
- $date = $+{date}; # must
- $time = $+{time}; # must
- $host = $+{host}; # should
- $id = $+{id}; # should
- $pid = $+{pid}; # should
- $mid = $+{mid}; # should
- $sdfield = $+{sdfield}; # should
- $cont = $+{cont}; # should
- }
-
- if(!$prival || !$date || !$time) {
- $err = 1;
- Log2Syslog_Log3slog ($hash, 2, "Log2Syslog $name - error parse msg -> $data");
- no warnings 'uninitialized';
- Log2Syslog_Log3slog ($hash, 5, "Log2Syslog $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;
- } 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;
- Log2Syslog_Log3slog ($hash, 2, "Log2Syslog $name - error parse msg -> $data");
- }
-
- # Längenbegrenzung nach RFC5424
- $id = substr($id,0, ($RFC5425len{ID}-1));
- $pid = substr($pid,0, ($RFC5425len{PID}-1));
- $mid = substr($mid,0, ($RFC5425len{MID}-1));
- $host = substr($host,0, ($RFC5425len{HST}-1));
-
- no warnings 'uninitialized';
- 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");
- $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++;
- }
- }
- }
-
- } elsif ($pp eq "TPLink-Switch") {
- # Parser für TPLink Switch
- # 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;
- Log2Syslog_Log3slog ($hash, 2, "Log2Syslog $name - error parse msg -> $data");
- } 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;
- Log2Syslog_Log3slog ($hash, 2, "Log2Syslog $name - error parse msg -> $data");
- }
-
- 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++;
- }
- }
- }
-
- } 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 = "";
- my $IGNORE = 0;
- eval $parseFn;
- if($@) {
- Log2Syslog_Log3slog ($hash, 2, "Log2Syslog $name -> error parseFn: $@");
- $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;
- $host = $HOST if(defined $HOST);
- $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);
- $ignore = $IGNORE if($IGNORE =~ /\d/);
-
- if($prival && 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, 2, "Log2Syslog $name - error parse msg -> $data");
- }
- 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
- $pl = "";
- 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.");
- }
- }
- return ($err,$ignore,$sev,$phost,$ts,$pl);
- }
- #################################################################################################
- # Syslog Collector Events erzeugen
- # (im Collector Model)
- #################################################################################################
- sub Log2Syslog_Trigger($$$) {
- my ($hash,$ts,$pl) = @_;
- 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}) {
- push @{$hash->{CHANGETIME}}, $ts;
- } else {
- $hash->{CHANGETIME}[0] = $ts;
- }
- my $ret = DoTrigger($name, undef, $no_replace);
-
- return;
- }
- ###############################################################################
- # Undef Funktion
- ###############################################################################
- sub Log2Syslog_Undef($$) {
- my ($hash, $name) = @_;
-
- RemoveInternalTimer($hash);
-
- Log2Syslog_closesock($hash,1); # Clientsocket schließen
- Log2Syslog_downServer($hash,1); # Serversocket schließen, kill children
- return undef;
- }
- ###############################################################################
- # Collector-Socket schließen
- ###############################################################################
- sub Log2Syslog_downServer($;$) {
- my ($hash,$delchildren) = @_;
- my $name = $hash->{NAME};
- my $port = $hash->{PORT};
- my $protocol = $hash->{PROTOCOL};
- my $ret;
-
- return if(!$hash->{SERVERSOCKET} || $hash->{MODEL} !~ /Collector/);
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Closing server socket $protocol/$port ...");
-
- if($protocol =~ /tcp/) {
- TcpServer_Close($hash);
- delete($hash->{CONNECTS});
- delete($hash->{SERVERSOCKET});
-
- if($delchildren) {
- my @children = devspec2array($name."_.*");
- foreach (@children) {
- my $child = $_;
- if($child ne $name."_.*") {
- CommandDelete(undef, $child);
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - child instance $child deleted.");
- }
- }
- delete($hash->{HELPER}{SSLALGO});
- delete($hash->{HELPER}{SSLVER});
- readingsSingleUpdate($hash, "SSL_Version", "n.a.", 1);
- readingsSingleUpdate($hash, "SSL_Algorithm", "n.a.", 1);
- }
- return;
- }
-
- $ret = $hash->{SERVERSOCKET}->close();
-
- Log2Syslog_Log3slog ($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
- ###############################################################################
- sub Log2Syslog_Delete($$) {
- my ($hash, $arg) = @_;
- delete $logInform{$hash->{NAME}};
- return undef;
- }
- ###############################################################################
- # 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 ".
- "reopen:noArg ".
- (($hash->{MODEL} =~ /Sender/)?"sendTestMessage ":"")
- ;
-
- return if(AttrVal($name, "disable", "") eq "1");
-
- if($opt =~ /sendTestMessage/) {
- my $own;
- if ($prop) {
- shift @a;
- shift @a;
- $own = join(" ",@a);
- }
- Log2Syslog_sendTestMsg($hash,$own);
-
- } elsif($opt =~ /reopen/) {
- $hash->{HELPER}{MEMLOCK} = 1;
- InternalTimer(gettimeofday()+2, "Log2Syslog_deleteMemLock", $hash, 0);
-
- Log2Syslog_closesock($hash,1); # Clientsocket schließen
- Log2Syslog_downServer($hash,1); # Serversocket schließen
- if($hash->{MODEL} =~ /Collector/) { # Serversocket öffnen
- InternalTimer(gettimeofday()+0.5, "Log2Syslog_initServer", "$name,global", 0);
- readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
- }
-
- } else {
- return "$setlist";
- }
-
- return undef;
- }
- ###############################################################################
- # 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 $st;
- my $getlist = "Unknown argument $opt, choose one of ".
- (($hash->{MODEL} !~ /Collector/)?"certInfo:noArg ":"").
- "versionNotes:noArg "
- ;
-
- return if(AttrVal($name, "disable", "") eq "1");
-
- my($sock,$cert,@certs);
- if ($opt =~ /certInfo/) {
- if(ReadingsVal($name,"SSL_Version","n.a.") ne "n.a.") {
- ($sock,$st) = Log2Syslog_opensock($hash,0);
- if($sock) {
- $cert = $sock->dump_peer_certificate();
- # Log2Syslog_closesock($hash);
- }
- }
- return $cert if($cert);
- return "no SSL session has been created";
-
- } elsif ($opt =~ /versionNotes/) {
- my $header = "<b>Module release information table</b><br>";
- my $header1 = "<b>Helpful hints</b><br>";
- my $i;
-
- # Ausgabetabelle erstellen
- my ($ret,$val0,$val1);
- $ret = "<html>";
-
- $ret .= sprintf("<div class=\"makeTable wide\"; style=\"text-align:left\">$header1 <br>");
- $ret .= "<table class=\"block wide internals\">";
- $ret .= "<tbody>";
- $ret .= "<tr class=\"even\">";
- $i = 0;
- foreach my $key (reverse sort(keys %Log2Syslog_vHintsExt)) {
- $val0 = $Log2Syslog_vHintsExt{$key};
- $ret .= sprintf("<td style=\"vertical-align:top\"><b>$key</b> </td><td style=\"vertical-align:top\">$val0</td>" );
- $ret .= "</tr>";
- $i++;
- if ($i & 1) {
- # $i ist ungerade
- $ret .= "<tr class=\"odd\">";
- } else {
- $ret .= "<tr class=\"even\">";
- }
- }
- $ret .= "</tr>";
- $ret .= "</tbody>";
- $ret .= "</table>";
- $ret .= "</div>";
- $ret .= sprintf("<div class=\"makeTable wide\"; style=\"text-align:left\">$header <br>");
- $ret .= "<table class=\"block wide internals\">";
- $ret .= "<tbody>";
- $ret .= "<tr class=\"even\">";
- $i = 0;
- foreach my $key (reverse sort(keys %Log2Syslog_vNotesExtern)) {
- ($val0,$val1) = split(/\s/,$Log2Syslog_vNotesExtern{$key},2);
- $ret .= sprintf("<td style=\"vertical-align:top\"><b>$key</b> </td><td style=\"vertical-align:top\">$val0 </td><td>$val1</td>" );
- $ret .= "</tr>";
- $i++;
- if ($i & 1) {
- # $i ist ungerade
- $ret .= "<tr class=\"odd\">";
- } else {
- $ret .= "<tr class=\"even\">";
- }
- }
- $ret .= "</tr>";
- $ret .= "</tbody>";
- $ret .= "</table>";
- $ret .= "</div>";
-
- $ret .= "</html>";
-
- return $ret;
-
- } else {
- return "$getlist";
- }
-
- return undef;
- }
- ###############################################################################
- sub Log2Syslog_Attr ($$$$) {
- my ($cmd,$name,$aName,$aVal) = @_;
- my $hash = $defs{$name};
- my ($do,$st);
-
- # $cmd can be "del" or "set"
- # $name is device name
- # aName and aVal are Attribute name and value
- if ($cmd eq "set" && $hash->{MODEL} !~ /Collector/ && $aName =~ /parseProfile|parseFn|outputFields|makeEvent/) {
- return "\"$aName\" is only valid for model \"Collector\"";
- }
-
- if ($cmd eq "set" && $hash->{MODEL} =~ /Collector/ && $aName =~ /addTimestamp|contDelimiter|addStateEvent|logFormat|octetCount|ssldebug|timeout/) {
- return "\"$aName\" is only valid for model \"Sender\"";
- }
-
- if ($aName eq "disable") {
- if($cmd eq "set") {
- return "Mode \"$aVal\" is only valid for model \"Sender\"" if($aVal eq "maintenance" && $hash->{MODEL} !~ /Sender/);
- $do = $aVal?1:0;
- }
- $do = 0 if($cmd eq "del");
- $st = ($do&&$aVal=~/maintenance/)?"maintenance":($do&&$aVal==1)?"disabled":"initialized";
-
- $hash->{HELPER}{MEMLOCK} = 1;
- InternalTimer(gettimeofday()+2, "Log2Syslog_deleteMemLock", $hash, 0);
-
- if($do==0 || $aVal=~/maintenance/) {
- if($hash->{MODEL} =~ /Collector/) {
- Log2Syslog_downServer($hash,1); # Serversocket schließen und wieder öffnen
- InternalTimer(gettimeofday()+0.5, "Log2Syslog_initServer", "$name,global", 0);
- }
- } else {
- Log2Syslog_closesock($hash,1); # Clientsocket schließen
- Log2Syslog_downServer($hash); # Serversocket schließen
- }
- }
-
- if ($aName eq "TLS") {
- if($cmd eq "set") {
- $do = ($aVal) ? 1 : 0;
- }
- $do = 0 if($cmd eq "del");
- if ($do == 0) {
- delete $hash->{SSL};
- } else {
- if($hash->{MODEL} =~ /Collector/) {
- $attr{$name}{protocol} = "TCP" if(AttrVal($name, "protocol", "UDP") ne "TCP");
- TcpServer_SetSSL($hash);
- }
- }
- $hash->{HELPER}{MEMLOCK} = 1;
- InternalTimer(gettimeofday()+2, "Log2Syslog_deleteMemLock", $hash, 0);
-
- Log2Syslog_closesock($hash,1); # Clientsocket schließen
- Log2Syslog_downServer($hash,1); # Serversocket schließen
- if($hash->{MODEL} =~ /Collector/) {
- InternalTimer(gettimeofday()+0.5, "Log2Syslog_initServer", "$name,global", 0); # Serversocket öffnen
- readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
- }
- }
-
- 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);
- RemoveInternalTimer($hash, "Log2Syslog_trate");
- InternalTimer(gettimeofday()+5, "Log2Syslog_trate", $hash, 0);
- }
-
- if ($cmd eq "set" && $aName =~ /port|timeout/) {
- if($aVal !~ m/^\d+$/) { return " The Value of \"$aName\" is not valid. Use only figures !";}
-
- $hash->{HELPER}{MEMLOCK} = 1;
- InternalTimer(gettimeofday()+2, "Log2Syslog_deleteMemLock", $hash, 0);
-
- if($aName =~ /port/ && $hash->{MODEL} =~ /Collector/ && $init_done) {
- 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,1); # Serversocket schließen
- InternalTimer(gettimeofday()+0.5, "Log2Syslog_initServer", "$name,global", 0);
- readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
- } elsif ($aName =~ /port/ && $hash->{MODEL} !~ /Collector/) {
- Log2Syslog_closesock($hash,1); # Clientsocket schließen
- }
- }
-
- if ($aName =~ /protocol/) {
- if($aVal =~ /UDP/) {
- $attr{$name}{TLS} = 0 if(AttrVal($name, "TLS", 0));
- }
- $hash->{HELPER}{MEMLOCK} = 1;
- InternalTimer(gettimeofday()+2, "Log2Syslog_deleteMemLock", $hash, 0);
-
- if($hash->{MODEL} eq "Collector") {
- Log2Syslog_downServer($hash,1); # Serversocket schließen
- InternalTimer(gettimeofday()+0.5, "Log2Syslog_initServer", "$name,global", 0);
- readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
- } else {
- Log2Syslog_closesock($hash,1); # Clientsocket schließen
- }
- }
-
- if ($cmd eq "set" && $aName =~ /parseFn/) {
- $_[3] = "{$aVal}" if($aVal !~ m/^\{.*\}$/s);
- $aVal = $_[3];
- my %specials = (
- "%IGNORE" => "0",
- "%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);
- }
-
- if ($aName =~ /parseProfile/) {
- if ($cmd eq "set" && $aVal =~ /ParseFn/) {
- return "You have to define a parse-function via attribute \"parseFn\" first !" if(!AttrVal($name,"parseFn",""));
- }
- if ($cmd eq "set") {
- $hash->{PROFILE} = $aVal;
- } else {
- $hash->{PROFILE} = "IETF";
- }
- readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
- }
-
- 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 !";
- }
-
- if ($aName =~ /makeEvent/) {
- foreach my $key(keys%{$defs{$name}{READINGS}}) {
- delete($defs{$name}{READINGS}{$key}) if($key !~ /state|Transfered_logs_per_minute|SSL_.*|Parse_Err_No/);
- }
- }
-
- return;
- }
- #################################################################################
- # Eventlogging
- #################################################################################
- sub Log2Syslog_eventlog($$) {
- # $hash is my entry, $dev is the entry of the changed device
- my ($hash,$dev) = @_;
- my $name = $hash->{NAME};
- my $rex = $hash->{HELPER}{EVNTLOG};
- my $st = ReadingsVal($name,"state","active");
- my $sendsev = AttrVal($name, "respectSeverity", ""); # Nachrichten welcher Schweregrade sollen gesendet werden
- my ($prival,$data,$sock,$pid,$sevAstxt);
-
- if(IsDisabled($name)) {
- $st = AttrVal($name, "disable", "0");
- $st = ($st =~ /maintenance/)?$st:"disabled";
- my $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
- readingsSingleUpdate($hash, "state", $st, $evt);
- $hash->{HELPER}{OLDSTATE} = $st;
- return;
- }
-
- if($init_done != 1 || !$rex || $hash->{MODEL} !~ /Sender/ || Log2Syslog_IsMemLock($hash)) {
- return;
- }
-
- 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};
-
- ($sock,$st) = Log2Syslog_opensock($hash,0);
-
- if($sock) {
- for (my $i = 0; $i < $max; $i++) {
- my $txt = $events->[$i];
- $txt = "" if(!defined($txt));
- $txt = Log2Syslog_charfilter($hash,$txt);
-
- my $tim = (($ct && $ct->[$i]) ? $ct->[$i] : $tn);
- my ($date,$time) = split(" ",$tim);
-
- if($n =~ m/^$rex$/ || "$n:$txt" =~ m/^$rex$/ || "$tim:$n:$txt" =~ m/^$rex$/) {
- my $otp = "$n $txt";
- $otp = "$tim $otp" if AttrVal($name,'addTimestamp',0);
- ($prival,$sevAstxt) = Log2Syslog_setprival($txt);
- if($sendsev && $sendsev !~ m/$sevAstxt/) {
- # nicht senden wenn Severity nicht in "respectSeverity" enthalten
- Log2Syslog_Log3slog($name, 5, "Log2Syslog $name - Warning - Payload NOT sent due to Message Severity not in attribute \"respectSeverity\"\n");
- next;
- }
- ($data,$pid) = Log2Syslog_setpayload($hash,$prival,$date,$time,$otp,"event");
- next if(!$data);
-
- my $ret = syswrite ($sock,$data);
- if($ret && $ret > 0) {
- Log2Syslog_Log3slog($name, 4, "Log2Syslog $name - Payload sequence $pid sent\n");
- } else {
- my $err = $!;
- Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - Warning - Payload sequence $pid NOT sent: $err\n");
- $st = "write error: $err";
- }
- }
- }
-
- Log2Syslog_closesock($hash) if($st =~ /^write error:.*/);
- }
-
- my $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
- readingsSingleUpdate($hash, "state", $st, $evt);
- $hash->{HELPER}{OLDSTATE} = $st;
-
- return "";
- }
- #################################################################################
- # FHEM system logging
- #################################################################################
- sub Log2Syslog_fhemlog($$) {
- my ($name,$raw) = @_;
- my $hash = $defs{$name};
- my $rex = $hash->{HELPER}{FHEMLOG};
- my $st = ReadingsVal($name,"state","active");
- my $sendsev = AttrVal($name, "respectSeverity", ""); # Nachrichten welcher Schweregrade sollen gesendet werden
- my ($prival,$sock,$err,$ret,$data,$pid,$sevAstxt);
-
- if(IsDisabled($name)) {
- $st = AttrVal($name, "disable", "1");
- $st = ($st =~ /maintenance/)?$st:"disabled";
- my $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
- readingsSingleUpdate($hash, "state", $st, $evt);
- $hash->{HELPER}{OLDSTATE} = $st;
- return;
- }
-
- if($init_done != 1 || !$rex || $hash->{MODEL} !~ /Sender/ || Log2Syslog_IsMemLock($hash)) {
- return;
- }
-
- my ($date,$time,$vbose,undef,$txt) = split(" ",$raw,5);
- $txt = Log2Syslog_charfilter($hash,$txt);
- $date =~ s/\./-/g;
- my $tim = $date." ".$time;
-
- if($txt =~ m/^$rex$/ || "$vbose: $txt" =~ m/^$rex$/) {
- my $otp = "$vbose: $txt";
- $otp = "$tim $otp" if AttrVal($name,'addTimestamp',0);
- ($prival,$sevAstxt) = Log2Syslog_setprival($txt,$vbose);
- if($sendsev && $sendsev !~ m/$sevAstxt/) {
- # nicht senden wenn Severity nicht in "respectSeverity" enthalten
- Log2Syslog_Log3slog($name, 5, "Log2Syslog $name - Warning - Payload NOT sent due to Message Severity not in attribute \"respectSeverity\"\n");
- return;
- }
-
- ($data,$pid) = Log2Syslog_setpayload($hash,$prival,$date,$time,$otp,"fhem");
- return if(!$data);
-
- ($sock,$st) = Log2Syslog_opensock($hash,0);
-
- if ($sock) {
- $ret = syswrite($sock,$data) if($data);
- if($ret && $ret > 0) {
- Log2Syslog_Log3slog($name, 4, "Log2Syslog $name - Payload sequence $pid sent\n");
- } else {
- my $err = $!;
- Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - Warning - Payload sequence $pid NOT sent: $err\n");
- $st = "write error: $err";
- }
-
- Log2Syslog_closesock($hash) if($st =~ /^write error:.*/);
- }
- }
-
- my $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
- readingsSingleUpdate($hash, "state", $st, $evt);
- $hash->{HELPER}{OLDSTATE} = $st;
- return;
- }
- #################################################################################
- # Test Message senden
- #################################################################################
- sub Log2Syslog_sendTestMsg($$) {
- my ($hash,$own) = @_;
- my $name = $hash->{NAME};
- my $st = ReadingsVal($name,"state","active");
- my ($prival,$ts,$sock,$tim,$date,$time,$err,$ret,$data,$pid,$otp);
-
- if($own) {
- # eigene Testmessage ohne Formatanpassung raw senden
- $data = $own;
- $pid = $hash->{SEQNO}; # PayloadID zur Nachverfolgung der Eventabfolge
- $hash->{SEQNO}++;
-
- } 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);
- }
-
- ($sock,$st) = Log2Syslog_opensock($hash,0);
-
- if ($sock) {
- $ret = syswrite $sock, $data."\n" if($data);
- if($ret && $ret > 0) {
- Log2Syslog_Log3slog($name, 4, "$name - Payload sequence $pid sent\n");
- $st = "maintenance";
- } else {
- my $err = $!;
- Log2Syslog_Log3slog($name, 3, "$name - Warning - Payload sequence $pid NOT sent: $err\n");
- $st = "write error: $err";
- }
-
- Log2Syslog_closesock($hash) if($st =~ /^write error:.*/);
- }
-
- my $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
- readingsSingleUpdate($hash, "state", $st, $evt);
- $hash->{HELPER}{OLDSTATE} = $st;
- return;
- }
- ###############################################################################
- # Helper für ident & Regex setzen
- ###############################################################################
- sub Log2Syslog_setidrex ($$) {
- 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
- ###############################################################################
- sub Log2Syslog_charfilter ($$) {
- 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;
- $txt =~ s/Ä/Ae/g;
- $txt =~ s/Ö/Oe/g;
- $txt =~ s/Ü/Ue/g;
- $txt =~ s/€/EUR/g;
- $txt =~ tr/ A-Za-z0-9!"#$%&'()*+,-.\/:;<=>?@[\]^_`{|}~//cd;
-
- return($txt);
- }
- ###############################################################################
- # erstelle Socket
- ###############################################################################
- sub Log2Syslog_opensock ($;$$) {
- my ($hash,$supresslog) = @_;
- 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"));
- my $st = ReadingsVal($name,"state","active");
- my $timeout = AttrVal($name, "timeout", 0.5);
- my $ssldbg = AttrVal($name, "ssldebug", 0);
- my ($sock,$lo,$lof,$sslver,$sslalgo);
-
- return undef if($init_done != 1 || $hash->{MODEL} !~ /Sender/);
-
- if($hash->{CLIENTSOCKET}) {
- return($hash->{CLIENTSOCKET},$st);
- }
-
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Opening client socket on port \"$port\" ...") if(!$supresslog);
-
- if(AttrVal($name, "TLS", 0)) {
- # TLS gesicherte Verbindung
- # TLS Transport nach RFC5425 https://tools.ietf.org/pdf/rfc5425.pdf
- $attr{$name}{protocol} = "TCP" if(AttrVal($name, "protocol", "UDP") ne "TCP");
- $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) {
- $st = "unable open socket for $host, $protocol, $port: $!";
- } else {
- $sock->blocking(1);
- $IO::Socket::SSL::DEBUG = $ssldbg;
- eval { IO::Socket::SSL->start_SSL($sock,
- SSL_verify_mode => 0,
- SSL_version => "TLSv1_2:!TLSv1_1:!SSLv3:!SSLv23:!SSLv2",
- SSL_hostname => $host,
- SSL_veriycn_scheme => "rfc5425",
- SSL_veriycn_publicsuffix => '',
- Timeout => $timeout
- ) || undef $sock; };
- $IO::Socket::SSL::DEBUG = 0;
- if($@) {
- $st = "SSL error: $@";
- undef $sock;
- } elsif (!$sock) {
- $st = "SSL error: ".IO::Socket::SSL::errstr();
- undef $sock;
- } else {
- $sslver = $sock->get_sslversion();
- $sslalgo = $sock->get_fingerprint();
- $sslalgo = (split("\\\$",$sslalgo))[0];
- $lof = "Socket opened for Host: $host, Protocol: $protocol, Port: $port, TLS: 1";
- $st = "active";
- }
- }
- }
- } else {
- # erstellt ungesicherte Socket Verbindung
- $sslver = "n.a.";
- $sslalgo = "n.a.";
- $sock = new IO::Socket::INET (PeerHost => $host, PeerPort => $port, Proto => $protocol, Timeout => $timeout );
- if (!$sock) {
- undef $sock;
- $st = "unable open socket for $host, $protocol, $port: $!";
- $lo = "Socket not opened: $!";
- } else {
- $sock->blocking(0);
- $st = "active";
- # Logausgabe (nur in das fhem Logfile !)
- $lof = "Socket opened for Host: $host, Protocol: $protocol, Port: $port, TLS: 0";
- }
- }
-
- if($sslver ne $hash->{HELPER}{SSLVER}) {
- readingsSingleUpdate($hash, "SSL_Version", $sslver, 1);
- $hash->{HELPER}{SSLVER} = $sslver;
- }
-
- if($sslalgo ne $hash->{HELPER}{SSLALGO}) {
- readingsSingleUpdate($hash, "SSL_Algorithm", $sslalgo, 1);
- $hash->{HELPER}{SSLALGO} = $sslalgo;
- }
-
- Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - $lo") if($lo);
- Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - $lof") if($lof && !$supresslog && !$hash->{CLIENTSOCKET});
-
- $hash->{CLIENTSOCKET} = $sock if($sock);
-
- return($sock,$st);
- }
- ###############################################################################
- # Socket schließen
- ###############################################################################
- sub Log2Syslog_closesock($;$$) {
- my ($hash,$dolog) = @_;
- my $name = $hash->{NAME};
- my $st = "closed";
- my $evt;
- my $sock = $hash->{CLIENTSOCKET};
- if($sock) {
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Closing client socket ...") if($dolog);
- shutdown($sock, 1);
- if(AttrVal($hash->{NAME}, "TLS", 0) && ReadingsVal($name,"SSL_Algorithm", "n.a.") ne "n.a.") {
- $sock->close(SSL_no_shutdown => 1);
- $hash->{HELPER}{SSLVER} = "n.a.";
- $hash->{HELPER}{SSLALGO} = "n.a.";
- readingsSingleUpdate($hash, "SSL_Version", "n.a.", 1);
- readingsSingleUpdate($hash, "SSL_Algorithm", "n.a.", 1);
- } else {
- $sock->close();
- }
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Client socket closed ...") if($dolog);
- delete($hash->{CLIENTSOCKET});
-
- if($dolog) {
- $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
- readingsSingleUpdate($hash, "state", $st, $evt);
- $hash->{HELPER}{OLDSTATE} = $st;
- }
- }
-
- return;
- }
- ###############################################################################
- # set PRIVAL (severity & facility)
- ###############################################################################
- sub Log2Syslog_setprival ($;$$) {
- my ($txt,$vbose) = @_;
- my ($prival,$sevAstxt);
-
- # Priority = (facility * 8) + severity
- # https://tools.ietf.org/pdf/rfc5424.pdf
-
- # determine facility
- my $fac = 5; # facility by syslogd
-
- # 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);
- }
-
- $sv = 3 if (lc($txt) =~ m/error/); # error condition
- $sv = 4 if (lc($txt) =~ m/warning/); # warning conditions
-
- $prival = ($fac*8)+$sv;
- $sevAstxt = $Log2Syslog_Severity{$sv};
-
- return($prival,$sevAstxt);
- }
- ###############################################################################
- # erstellen Payload für Syslog
- ###############################################################################
- sub Log2Syslog_setpayload ($$$$$$) {
- my ($hash,$prival,$date,$time,$otp,$lt) = @_;
- my $name = $hash->{NAME};
- my $ident = ($hash->{HELPER}{IDENT}?$hash->{HELPER}{IDENT}:$name)."_".$lt;
- my $myhost = $hash->{MYHOST}?$hash->{MYHOST}:"0.0.0.0";
- my $myfqdn = $hash->{MYFQDN}?$hash->{MYFQDN}:$myhost;
- my $lf = AttrVal($name, "logFormat", "IETF");
- my $cdl = AttrVal($name, "contDelimiter", ""); # Trennzeichen vor Content (z.B. für Synology nötig)
- my $data;
-
- return undef,undef if(!$otp);
- my $pid = $hash->{SEQNO}; # PayloadID zur Nachverfolgung der Eventabfolge
- $hash->{SEQNO}++;
- my ($year,$month,$day) = split("-",$date);
-
- if ($lf eq "BSD") {
- # BSD Protokollformat https://tools.ietf.org/html/rfc3164
- $time = (split(/\./,$time))[0] if($time =~ m/\./); # msec ist nicht erlaubt
- $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
- my $tag = substr($ident,0, $RFC3164len{TAG}); # Länge TAG Feld begrenzen
- no warnings 'uninitialized';
- $tag = $tag."[$pid]: ".$cdl; # TAG-Feld um PID und Content-Delimiter ergänzen
- $data = "<$prival>$month $day $time $myhost $tag$otp";
- use warnings;
- $data = substr($data,0, ($RFC3164len{DL}-1)); # Länge Total begrenzen
- }
-
- if ($lf eq "IETF") {
- # IETF Protokollformat https://tools.ietf.org/html/rfc5424
-
- 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));
- $myfqdn = substr($myfqdn,0, ($RFC5425len{HST}-1));
-
- no warnings 'uninitialized';
- if ($IETFver == 1) {
- $data = "<$prival>$IETFver $tim $myfqdn $ident $pid $mid $sdfield $cdl$otp";
- }
- use warnings;
- }
-
- if($data =~ /\s$/) {$data =~ s/\s$//;}
- $data = $data."\n";
- my $dl = length($data); # Länge muss ! für TLS stimmen, sonst keine Ausgabe !
-
- # wenn Transport Layer Security (TLS) -> Transport Mapping for Syslog https://tools.ietf.org/pdf/rfc5425.pdf
- # oder Octet counting -> Transmission of Syslog Messages over TCP https://tools.ietf.org/html/rfc6587
- if(AttrVal($name, "TLS", 0) || AttrVal($name, "octetCount", 0)) {
- $data = "$dl $data";
- Log2Syslog_Log3slog($name, 4, "$name - Payload created with octet count length: ".$dl);
- }
-
- my $ldat = ($dl>130)?(substr($data,0, 130)." ..."):$data;
- Log2Syslog_Log3slog($name, 4, "$name - Payload sequence $pid created:\n$ldat");
-
- return($data,$pid);
- }
- ###############################################################################
- # eigene Log3-Ableitung - Schleife vermeiden
- ###############################################################################
- sub Log2Syslog_Log3slog($$$) {
- 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;
- }
- ###############################################################################
- # Bestimmung Übertragungsrate
- ###############################################################################
- sub Log2Syslog_trate($) {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- my $rerun = AttrVal($name, "rateCalcRerun", 60);
-
- 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();
-
- my $ospm = ReadingsVal($name, "Transfered_logs_per_minute", 0);
- if($spm != $ospm) {
- readingsSingleUpdate($hash, "Transfered_logs_per_minute", $spm, 1);
- } else {
- readingsSingleUpdate($hash, "Transfered_logs_per_minute", $spm, 0);
- }
- }
-
- RemoveInternalTimer($hash, "Log2Syslog_trate");
- InternalTimer(gettimeofday()+$rerun, "Log2Syslog_trate", $hash, 0);
- return;
- }
- ###############################################################################
- # Peer IP-Adresse und Host ermitteln (Sender der Message)
- ###############################################################################
- sub Log2Syslog_evalPeer($) {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- my $socket = $hash->{SERVERSOCKET};
- my $protocol = lc(AttrVal($name, "protocol", "udp"));
- if($hash->{TEMPORARY}) {
- # temporäre Instanz abgelegt durch TcpServer_Accept
- $protocol = "tcp";
- }
- my ($phost,$paddr,$pport, $pipaddr);
-
- no warnings 'uninitialized';
- if($protocol =~ /tcp/) {
- $pipaddr = $hash->{HELPER}{TCPPADDR}; # gespeicherte IP-Adresse
- $phost = $hash->{HIPCACHE}{$pipaddr}; # zuerst IP/Host-Kombination aus Cache nehmen falls vorhanden
- if(!$phost) {
- $paddr = inet_aton($pipaddr);
- $phost = gethostbyaddr($paddr, AF_INET);
- $hash->{HIPCACHE}{$pipaddr} = $phost if($phost);
- }
- } elsif ($protocol =~ /udp/ && $socket) {
- # Protokoll UDP
- ($pport, $paddr) = sockaddr_in($socket->peername) if($socket->peername);
- $pipaddr = inet_ntoa($paddr) if($paddr);
- $phost = $hash->{HIPCACHE}{$pipaddr}; # zuerst IP/Host-Kombination aus Cache nehmen falls vorhanden
- if(!$phost) {
- $phost = gethostbyaddr($paddr, AF_INET);
- $hash->{HIPCACHE}{$pipaddr} = $phost if($phost);
- }
- }
- Log2Syslog_Log3slog ($hash, 5, "Log2Syslog $name - message peer: $phost,$pipaddr");
- use warnings;
- $phost = $phost?$phost:$pipaddr?$pipaddr:"unknown";
- return ($phost);
- }
- ###############################################################################
- # Memory-Lock
- # - solange gesetzt erfolgt keine Socketöffnung
- # - löschen Sperre über Internaltimer
- ###############################################################################
- sub Log2Syslog_IsMemLock($) {
- my ($hash) = @_;
- my $ret = 0;
-
- $ret = 1 if($hash->{HELPER}{MEMLOCK});
- return ($ret);
- }
- sub Log2Syslog_deleteMemLock($) {
- my ($hash) = @_;
-
- RemoveInternalTimer($hash, "Log2Syslog_deleteMemLock");
- delete($hash->{HELPER}{MEMLOCK});
- return;
- }
- 1;
- =pod
- =item helper
- =item summary forward FHEM system logs/events to a syslog server/act as an syslog server
- =item summary_DE sendet FHEM Logs/Events an Syslog-Server / agiert als Syslog-Server
- =begin html
- <a name="Log2Syslog"></a>
- <h3>Log2Syslog</h3>
- <ul>
- The module sends FHEM systemlog entries and/or FHEM events to an external syslog server or act itself as an Syslog-Server
- to receive Syslog-messages of other Devices which are able to send Syslog. <br>
- The syslog protocol has been implemented according the specifications of <a href="https://tools.ietf.org/html/rfc5424"> RFC5424 (IETF)</a>,
- <a href="https://tools.ietf.org/html/rfc3164"> RFC3164 (BSD)</a> and the TLS transport protocol according to
- <a href="https://tools.ietf.org/pdf/rfc5425.pdf"> RFC5425</a>. <br>
- <br>
-
- <b>Prerequisits</b>
- <ul>
- <br/>
- The additional perl modules "IO::Socket::INET" and "IO::Socket::SSL" (if SSL is used) must be installed on your system. <br>
- Install this package from cpan or, on Debian based installations, better by: <br><br>
-
- <code>sudo apt-get install libio-socket-multicast-perl</code><br>
- <code>sudo apt-get install libio-socket-ssl-perl</code><br><br>
-
- </ul>
- <br>
-
- <a name="Log2Syslogdefine"></a>
- <b>Definition and usage</b>
- <ul>
- <br>
- Depending of the intended purpose a Syslog-Server (MODEL Collector) or a Syslog-Client (MODEL Sender) can be
- defined. <br>
- The Collector receives messages in Syslog-format of other Devices and hence generates Events/Readings for further
- processing. The Sender-Device forwards FHEM Systemlog entries and/or Events to an external Syslog-Server. <br>
- </ul>
-
- <br>
- <b><h4> The Collector (Syslog-Server) </h4></b>
- <ul>
- <b> Definition of a Collector </b>
- <br>
-
- <ul>
- <br>
- <code>define <name> Log2Syslog </code><br>
- <br>
- </ul>
-
- The Definition don't need any further parameter.
- In basic setup the Syslog-Server is initialized with Port=1514/UDP and the Parsingprofil "IETF".
- By the <a href="#Log2Syslogattr">attribute</a> "parseProfile" another formats (e.g. BSD) can be selected.
- The Syslog-Server is immediately ready for use, is parsing the Syslog-data accordingly the rules of RFC5424 and
- generates FHEM-Events from received Syslog-messages (pls. see Eventmonitor for parsed data). <br><br>
-
- <br>
- <b>Example of a Collector: </b><br>
-
- <ul>
- <br>
- <code>define SyslogServer Log2Syslog </code><br>
- <br>
- </ul>
-
- The generated events are visible in the FHEM-Eventmonitor. <br>
- <br>
- Example of generated Events with attribute 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>
- To separate fields the string "||" is used.
- The meaning of the fields in the example is:
- <br><br>
-
- <ul>
- <table>
- <colgroup> <col width=20%> <col width=80%> </colgroup>
- <tr><td> <b>HOST</b> </td><td> the Sender of the dataset </td></tr>
- <tr><td> <b>FAC</b> </td><td> Facility corresponding to RFC5424 </td></tr>
- <tr><td> <b>SEV</b> </td><td> Severity corresponding to RFC5424 </td></tr>
- <tr><td> <b>ID</b> </td><td> Ident-Tag </td></tr>
- <tr><td> <b>CONT</b> </td><td> the message part of the received message </td></tr>
- </table>
- </ul>
- <br>
-
- The timestamp of generated events is parsed from the Syslog-message. If this information isn't delivered, the current
- timestamp of the operating system is used. <br>
- The reading name in the generated event match the parsed hostname from Syslog-message.
- If the message don't contain a hostname, the IP-address of the sender is retrieved from the network interface and
- the hostname is determined if possible.
- In this case the determined hostname respectively the IP-address is used as Reading in the generated event.
- <br>
- After definition of a Collectors Syslog-messages in IETF-format according to RFC5424 are expected. If the data are not
- delivered in this record format and can't be parsed, the Reading "state" will contain the message
- <b>"parse error - see logfile"</b> and the received Syslog-data are printed into the FHEM Logfile in raw-format. The
- reading "Parse_Err_No" contains the number of parse-errors since module start.<br>
-
- By the <a href="#Log2Syslogattr">attribute</a> "parseProfile" you can try to use another predefined parse-profile
- or you can create an own parse-profile as well. <br><br>
-
- To define an <b>own parse function</b> the
- "parseProfile = ParseFn" has to be set and with <a href="#Log2Syslogattr">attribute</a> "parseFn" a specific
- parse function has to be provided. <br>
- The fields used by the event and their sequential arrangement can be selected from a range with
- <a href="#Log2Syslogattr">attribute</a> "outputFields". Depending from the used parse-profil all or a subset of
- the available fields can be selected. Further information about it you can find in description of attribute
- "parseProfile". <br>
- <br>
- The behavior of the event generation can be adapted by <a href="#Log2Syslogattr">attribute</a> "makeEvent". <br>
- </ul>
-
- <br>
- <b><h4> The Sender (Syslog-Client) </h4></b>
- <ul>
- <b> Definition of a Sender </b>
- <br>
-
- <ul>
- <br>
- <code>define <name> Log2Syslog <destination host> [ident:<ident>] [event:<regexp>] [fhem:<regexp>]</code><br>
- <br>
- </ul>
-
- <ul>
- <table>
- <colgroup> <col width=25%> <col width=75%> </colgroup>
- <tr><td> <b><destination host></b> </td><td> host (name or IP-address) where the syslog server is running </td></tr>
- <tr><td> <b>[ident:<ident>]</b> </td><td> optional program identifier. If not set the device name will be used as default. </td></tr>
- <tr><td> <b>[event:<regexp>]</b> </td><td> optional regex to filter events for logging </td></tr>
- <tr><td> <b>[fhem:<regexp>]</b> </td><td> optional regex to filter fhem system log for logging </td></tr>
- </table>
- </ul>
-
- <br><br>
-
- 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 is set. <br>
- Without setting a regex, no fhem system log or event log will be forwarded. <br><br>
- The verbose level of FHEM system logs are converted into equivalent syslog severity level. <br>
- Thurthermore the message text will be scanned for signal terms "warning" and "error" (with case insensitivity).
- Dependent of it the severity will be set equivalent as well. If a severity is already set by verbose level, it will 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=50%> <col width=50%> </colgroup>
- <tr><td> <b>verbose-Level</b> </td><td> <b>Severity 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>
- <br>
-
- <b>Example of a Sender: </b><br>
-
- <ul>
- <br>
- <code>define splunklog Log2Syslog fhemtest 192.168.2.49 ident:Test event:.* fhem:.* </code><br/>
- <br>
- </ul>
-
- All events are forwarded like this exmple of a raw-print of a Splunk Syslog Servers shows:<br/>
- <pre>
- Aug 18 21:06:46 fhemtest.myds.me 1 2017-08-18T21: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-18T21: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-18T21: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-18T21: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-18T21:08:27.095 fhemtest.myds.me Test_fhem 13339 FHEM [version@Log2Syslog version="4.2.0"] : 4: CamTER - CAMID already set - ignore get camid
- </pre>
-
- The structure of the payload differs dependent of the used logFormat. <br><br>
-
- <b>logFormat IETF:</b> <br><br>
- "<PRIVAL>IETFVERS TIME MYHOST IDENT PID MID [SD-FIELD] 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> IETFVERS </td><td> used version of RFC5424 specification </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> SD-FIELD </td><td> contains additional iformation about used module version </td></tr>
- <tr><td> MESSAGE </td><td> the dataset to transfer </td></tr>
- </table>
- </ul>
- <br>
-
- <b>logFormat BSD:</b> <br><br>
- "<PRIVAL>MONTH DAY TIME MYHOST IDENT[PID]: 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> MONTH </td><td> month according to RFC3164 </td></tr>
- <tr><td> DAY </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> TAG </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> the message-id (sequence number) </td></tr>
- <tr><td> MESSAGE </td><td> the dataset to transfer </td></tr>
- </table>
- </ul>
- <br>
-
- </ul>
- <br>
- <a name="Log2SyslogSet"></a>
- <b>Set</b>
- <ul>
- <br>
-
- <ul>
- <li><b>reopen </b><br>
- <br>
- Closes an existing Client/Server-connection and open it again.
- This command can be helpful in case of e.g. "broken pipe"-errors.
- </li>
- </ul>
- <br>
-
- <ul>
- <li><b>sendTestMessage [<Message>] </b><br>
- <br>
- With device type "Sender" a testmessage can be transfered. The format of the message depends on attribute "logFormat"
- and contains data in BSD- or IETF-format.
- Alternatively an own <Message> can be set. This message will be sent in im raw-format without
- any conversion. The attribute "disable = maintenance" determines, that no data except test messages are sent
- to the receiver.
- </li>
- </ul>
- <br>
- </ul>
- <br>
-
- <a name="Log2SyslogGet"></a>
- <b>Get</b>
- <ul>
- <br>
-
- <ul>
- <li><b>certinfo </b><br>
- <br>
- On a SenderDevice the command shows informations about the server certificate in case a TLS-session was created
- (Reading "SSL_Version" isn't "n.a.").
- </li>
- </ul>
- <br>
-
- <ul>
- <li><b>versionNotes </b><br>
- <br>
- Shows release informations and hints about the module. Contains only main informations for module users.
- </li>
- </ul>
- <br>
- </ul>
- <br>
-
- <a name="Log2Syslogattr"></a>
- <b>Attributes</b>
- <ul>
- <br>
-
- <ul>
- <a name="addTimestamp"></a>
- <li><b>addTimestamp </b><br>
- <br/>
- The attribute is only usable for device type "Sender".
- If set, FHEM timestamps will be logged too.<br>
- Default behavior is not log these timestamps, because syslog uses own timestamps.<br>
- Maybe useful if mseclog is activated in FHEM.<br>
- <br>
-
- Example output (raw) of a Splunk syslog server: <br>
- <pre>Aug 18 21:26:55 fhemtest.myds.me 1 2017-08-18T21: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-18T21: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-18T21:26:54 fhemtest.myds.me Test_event 13339 FHEM - : 2017-08-18 21:26:54 recalc_Bezug state: Next: 21:31:59
- </pre>
- </li>
- </ul>
- <br>
- <ul>
- <a name="addStateEvent"></a>
- <li><b>addStateEvent </b><br>
- <br>
- The attribute is only usable for device type "Sender".
- If set, events will be completed with "state" if a state-event appears. <br>
- Default behavior is without getting "state".
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="contDelimiter"></a>
- <li><b>contDelimiter </b><br>
- <br>
- The attribute is only usable for device type "Sender".
- You can set an additional character which is straight inserted before the content-field. <br>
- This possibility is useful in some special cases if the receiver need it (e.g. the Synology-Protokollcenter needs the
- character ":" for proper function).
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="disable"></a>
- <li><b>disable [1 | 0 | maintenance] </b><br>
- <br>
- This device will be activated, deactivated respectSeverity set into the maintenance-mode.
- In maintenance-mode a test message can be sent by the "Sender"-device (pls. see also command "set <name>
- sendTestMessage").
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="logFormat"></a>
- <li><b>logFormat [ BSD | IETF ]</b><br>
- <br>
- This attribute is only usable for device type "Sender".
- Set the syslog protocol format. <br>
- Default value is "IETF" if not specified.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="makeEvent"></a>
- <li><b>makeEvent [ intern | no | reading ]</b><br>
- <br>
- The attribute is only usable for device type "Collector".
- With this attribute the behavior of the event- and reading generation is defined.
- <br><br>
-
- <ul>
- <table>
- <colgroup> <col width=10%> <col width=90%> </colgroup>
- <tr><td> <b>intern</b> </td><td> events are generated by module intern mechanism and only visible in FHEM eventmonitor. Readings are not created. </td></tr>
- <tr><td> <b>no</b> </td><td> only readings like "MSG_<hostname>" without event generation are created </td></tr>
- <tr><td> <b>reading</b> </td><td> readings like "MSG_<hostname>" are created. Events are created dependent of the "event-on-.*"-attributes </td></tr>
- </table>
- </ul>
-
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="octetCount"></a>
- <li><b>octetCount </b><br>
- <br>
- The attribute is only usable for device type "Sender". <br>
- If set, the Syslog Framing is changed from Non-Transparent-Framing (default) to Octet-Framing.
- The Syslog-Reciver must support Octet-Framing !
- For further informations see RFC6587 <a href="https://tools.ietf.org/html/rfc6587">"Transmission of Syslog Messages
- over TCP"</a>.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="outputFields"></a>
- <li><b>outputFields </b><br>
- <br>
- The attribute is only usable for device type "Collector".
- By a sortable list the desired fields of generated events can be selected.
- The meaningful usable fields are depending on the attribute <b>"parseProfil"</b>. Their meaning can be found in
- the description of attribute "parseProfil".
- Is "outputFields" not defined, a predefined set of fields for event generation is used.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="parseFn"></a>
- <li><b>parseFn {<Parsefunktion>} </b><br>
- <br>
- The attribute is only usable for device type "Collector".
- The provided perl function (has to be set into "{}") will be applied to the received Syslog-message.
- The following variables are commited to the function. They can be used for programming, processing and for
- value return. Variables which are provided as blank, are marked as "". <br>
- In case of restrictions the expected format of variables return is specified in "()".
- Otherwise the variable is usable for free.
- <br><br>
-
- <ul>
- <table>
- <colgroup> <col width=20%> <col width=80%> </colgroup>
- <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>
- <tr><td> $TS </td><td> Timestamp (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> provided raw-data of received Syslog-message (no evaluation of value return!) </td></tr>
- <tr><td> $IGNORE </td><td> 0 (0|1), if $IGNORE==1 the Syslog-dataset is ignored </td></tr>
- </table>
- </ul>
- <br>
- The names of the variables corresponding to the field names and their primary meaning denoted in attribute
- <b>"parseProfile"</b> (explanation of the field data). <br><br>
- <ul>
- <b>Example: </b> <br>
- # Source text: '<4> <;4>LAN IP and mask changed to 192.168.2.3 255.255.255.0' <br>
- # Task: The characters '<;4>' are to removed from the CONT-field
- <pre>
- {
- ($PRIVAL,$CONT) = ($DATA =~ /^<(\d{1,3})>\s(.*)$/);
- $CONT = (split(">",$CONT))[1] if($CONT =~ /^<.*>.*$/);
- }
- </pre>
- </ul>
-
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="parseProfile"></a>
- <li><b>parseProfile [ BSD | IETF | ... | ParseFn | raw ] </b><br>
- <br>
- Selection of a parse profile. The attribute is only usable for device type "Collector".
- <br><br>
-
- <ul>
- <table>
- <colgroup> <col width=20%> <col width=80%> </colgroup>
- <tr><td> <b>BSD</b> </td><td> Parsing of messages in BSD-format according to RFC3164 </td></tr>
- <tr><td> <b>IETF</b> </td><td> Parsing of messages in IETF-format according to RFC5424 (default) </td></tr>
- <tr><td> <b>...</b> </td><td> further specific parse profiles for selective device are provided </td></tr>
- <tr><td> <b>ParseFn</b> </td><td> Usage of an own specific parse function provided by attribute "parseFn" </td></tr>
- <tr><td> <b>raw</b> </td><td> no parsing, events are created from the messages as received without conversion </td></tr>
- </table>
- </ul>
- <br>
- The parsed data are provided in fields. The fields to use for events and their sequence can be defined by
- attribute <b>"outputFields"</b>. <br>
- Dependent from used "parseProfile" the following fields are filled with values and therefor it is meaningful
- to use only the namend fields by attribute "outputFields". By the "raw"-profil the received data are not converted
- and the event is created directly.
- <br><br>
-
- The meaningful usable fields in attribute "outputFields" depending of the particular profil:
- <br>
- <br>
- <ul>
- <table>
- <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>-> no selection is meaningful, the original message is used for event creation </td></tr>
- </table>
- </ul>
- <br>
-
- Explanation of field data:
- <br>
- <br>
- <ul>
- <table>
- <colgroup> <col width=20%> <col width=80%> </colgroup>
- <tr><td> PRIVAL </td><td> coded Priority value (coded from "facility" and "severity") </td></tr>
- <tr><td> FAC </td><td> decoded Facility </td></tr>
- <tr><td> SEV </td><td> decoded Severity of message </td></tr>
- <tr><td> TS </td><td> Timestamp containing date and time (YYYY-MM-DD hh:mm:ss) </td></tr>
- <tr><td> HOST </td><td> Hostname / Ip-address of the Sender </td></tr>
- <tr><td> DATE </td><td> Date (YYYY-MM-DD) </td></tr>
- <tr><td> TIME </td><td> Time (hh:mm:ss) </td></tr>
- <tr><td> ID </td><td> Device or application what was sending the Syslog-message </td></tr>
- <tr><td> PID </td><td> Programm-ID, offen reserved by process name or prozess-ID </td></tr>
- <tr><td> MID </td><td> Type of message (arbitrary string) </td></tr>
- <tr><td> SDFIELD </td><td> Metadaten about the received Syslog-message </td></tr>
- <tr><td> CONT </td><td> Content of the message </td></tr>
- <tr><td> DATA </td><td> received raw-data </td></tr>
- </table>
- </ul>
- <br>
-
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="port"></a>
- <li><b>port <Port></b><br>
- <br>
- The used port. For a Sender the default-port is 514.
- A Collector (Syslog-Server) uses the port 1514 per default.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="protocol"></a>
- <li><b>protocol [ TCP | UDP ]</b><br>
- <br>
- Sets the socket protocol which should be used. You can choose UDP or TCP. <br>
- Default value is "UDP" if not specified.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="rateCalcRerun"></a>
- <li><b>rateCalcRerun <Zeit in Sekunden> </b><br>
- <br>
- Rerun cycle for calculation of log transfer rate (Reading "Transfered_logs_per_minute") in seconds (>=60).
- Values less than 60 seconds are corrected to 60 seconds automatically.
- Default is 60 seconds.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="respectSeverity"></a>
- <li><b>respectSeverity </b><br>
- <br>
- Messages are only forwarded (Sender) respectively the receipt considered (Collector), whose severity is included
- by this attribute.
- If "respectSeverity" isn't set, messages of all severity is processed.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="sslCertPrefix"></a>
- <li><b>sslCertPrefix</b><br>
- <br>
- Set the prefix for the SSL certificate, default is "certs/server-".
- Setting this attribute you are able to specify different SSL-certificates for different Log2Syslog devices.
- See also the TLS attribute.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="ssldebug"></a>
- <li><b>ssldebug</b><br>
- <br>
- Debugging level of SSL messages. The attribute is only usable for device type "Sender". <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>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="TLS"></a>
- <li><b>TLS</b><br>
- <br>
- A client (Sender) establish a secured connection to a Syslog-Server.
- A Syslog-Server (Collector) provide to establish a secured connection.
- The protocol will be switched to TCP automatically.
- <br<br>
-
- Thereby a Collector device can use TLS, a certificate has to be created or available.
- With following steps a certicate can be created: <br><br>
-
- 1. in the FHEM basis directory create the directory "certs": <br>
- <pre>
- sudo mkdir /opt/fhem/certs
- </pre>
-
- 2. create the SSL certicate: <br>
- <pre>
- cd /opt/fhem/certs
- sudo openssl req -new -x509 -nodes -out server-cert.pem -days 3650 -keyout server-key.pem
- </pre>
-
- 3. set file/directory permissions: <br>
- <pre>
- sudo chown -R fhem:dialout /opt/fhem/certs
- sudo chmod 644 /opt/fhem/certs/*.pem
- sudo chmod 711 /opt/fhem/certs
- </pre>
-
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="timeout"></a>
- <li><b>timeout</b><br>
- <br>
- This attribute is only usable for device type "Sender".
- Timeout für die Verbindung zum Syslog-Server (TCP). Default: 0.5s.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="verbose"></a>
- <li><b>verbose</b><br>
- <br>
- Please see global <a href="#attributes">attribute</a> "verbose".
- To avoid loops, the output of verbose level of the Log2Syslog-Devices will only be reported into the local FHEM
- Logfile and not forwarded.
- </li>
- </ul>
- <br>
- <br>
-
- </ul>
- <br>
-
- <a name="Log2Syslogreadings"></a>
- <b>Readings</b>
- <ul>
- <br>
- <table>
- <colgroup> <col width=35%> <col width=65%> </colgroup>
- <tr><td><b>MSG_<Host></b> </td><td> the last successful parsed Syslog-message from <Host> </td></tr>
- <tr><td><b>Parse_Err_No</b> </td><td> the number of parse errors since start </td></tr>
- <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>
-
- </ul>
- =end html
- =begin html_DE
- <a name="Log2Syslog"></a>
- <h3>Log2Syslog</h3>
- <ul>
- Das Modul sendet 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>
- 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>
-
- <b>Voraussetzungen</b>
- <ul>
- <br/>
- Es werden die Perl Module "IO::Socket::INET" und "IO::Socket::SSL" (wenn SSL benutzt) benötigt und müssen installiert sein. <br>
- Das Modul kann über CPAN oder, auf Debian Linux Systemen, besser mit <br><br>
-
- <code>sudo apt-get install libio-socket-multicast-perl</code><br>
- <code>sudo apt-get install libio-socket-ssl-perl</code><br><br>
-
- installiert werden.
- </ul>
- <br/>
-
- <a name="Log2Syslogdefine"></a>
- <b>Definition und Verwendung</b>
- <ul>
- <br>
- Je nach Verwendungszweck kann ein Syslog-Server (MODEL Collector) oder ein Syslog-Client (MODEL Sender) definiert
- werden. <br>
- Der Collector empfängt Meldungen im Syslog-Format anderer Geräte und generiert daraus Events/Readings zur Weiterverarbeitung in
- FHEM. Das Sender-Device leitet FHEM Systemlog Einträge und/oder Events an einen externen Syslog-Server weiter. <br>
- </ul>
-
- <br>
- <b><h4> Der Collector (Syslog-Server) </h4></b>
- <ul>
- <b> Definition eines Collectors </b>
- <br>
-
- <ul>
- <br>
- <code>define <name> Log2Syslog </code><br>
- <br>
- </ul>
-
- Die Definition benötigt keine weiteren Parameter.
- 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.
- Der Syslog-Server ist sofort betriebsbereit, parst die Syslog-Daten entsprechend der Richtlinien nach RFC5424 und generiert
- aus den eingehenden Syslog-Meldungen FHEM-Events (Daten sind im Eventmonitor sichtbar). <br><br>
-
- <br>
- <b>Beispiel für einen Collector: </b><br>
-
- <ul>
- <br>
- <code>define SyslogServer Log2Syslog </code><br>
- <br>
- </ul>
-
- 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>
- Zwischen den einzelnen Feldern wird der Trenner "||" verwendet.
- Die Bedeutung der Felder in diesem Beispiel sind:
- <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>
- <tr><td> <b>CONT</b> </td><td> der Nachrichtenteil der empfangenen Meldung </td></tr>
- </table>
- </ul>
- <br>
-
- Der Timestamp der generierten Events wird aus den Syslogmeldungen geparst. Sollte diese Information nicht mitgeliefert
- werden, wird der aktuelle Timestamp des Systems verwendet. <br>
- Der Name des Readings im generierten Event entspricht dem aus der Syslogmeldung geparsten Hostnamen.
- 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.
- <br>
- Nach der Definition des Collectors werden die Syslog-Meldungen im IETF-Format gemäß RFC5424 erwartet. Werden die Daten
- 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. Das Reading
- "Parse_Err_No" enthält die Anzahl der Parse-Fehler seit Modulstart. <br>
-
- In diesem Fall kann mit dem <a href="#Log2Syslogattr">Attribut</a> "parseProfile" ein anderes vordefiniertes Parse-Profil
- eingestellt bzw. ein eigenes Profil definiert werden. <br><br>
-
- Zur Definition einer <b>eigenen Parse-Funktion</b> wird
- "parseProfile = ParseFn" eingestellt und im <a href="#Log2Syslogattr">Attribut</a> "parseFn" eine spezifische
- Parse-Funktion 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 Parse-Funktion können alle oder
- nur eine Untermenge der verfügbaren Felder verwendet werden. Näheres dazu in der Beschreibung des Attributes "parseProfile". <br>
- <br>
- Das Verhalten der Eventgenerierung kann mit dem <a href="#Log2Syslogattr">Attribut</a> "makeEvent" angepasst werden. <br>
- </ul>
-
- <br>
- <b><h4> Der Sender (Syslog-Client) </h4></b>
- <ul>
- <b> Definition eines Senders </b>
- <br>
-
- <ul>
- <br>
- <code>define <name> Log2Syslog <Zielhost> [ident:<ident>] [event:<regexp>] [fhem:<regexp>] </code><br>
- <br>
- </ul>
-
- <ul>
- <table>
- <colgroup> <col width=20%> <col width=80%> </colgroup>
- <tr><td> <b><Zielhost></b> </td><td> Host (Name oder IP-Adresse) auf dem der Syslog-Server läuft </td></tr>
- <tr><td> <b>[ident:<ident>]</b> </td><td> optionaler Programm Identifier. Wenn nicht gesetzt wird per default der Devicename benutzt. </td></tr>
- <tr><td> <b>[event:<regexp>]</b> </td><td> optionaler regulärer Ausdruck zur Filterung von Events zur Weiterleitung </td></tr>
- <tr><td> <b>[fhem:<regexp>]</b> </td><td> optionaler regulärer Ausdruck zur Filterung von FHEM Logs zur Weiterleitung </td></tr>
- </table>
- </ul>
-
- <br><br>
-
- Direkt nach der Definition sendet das neue Device alle neu auftretenden FHEM Systemlog Einträge und Events ohne weitere
- 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
- (Groß- /Kleinschreibung wird nicht beachtet). Davon abhängig wird der Schweregrad ebenfalls äquivalent gesetzt und übersteuert
- 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>
- <br>
-
- <b>Beispiel für einen Sender: </b><br>
-
- <ul>
- <br>
- <code>define splunklog Log2Syslog fhemtest 192.168.2.49 ident:Test event:.* fhem:.* </code><br/>
- <br>
- </ul>
-
- Es werden alle Events weitergeleitet wie deses Beispiel der raw-Ausgabe eines Splunk Syslog Servers zeigt:<br/>
- <pre>
- Aug 18 21:06:46 fhemtest.myds.me 1 2017-08-18T21: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-18T21: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-18T21: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-18T21: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-18T21:08:27.095 fhemtest.myds.me Test_fhem 13339 FHEM [version@Log2Syslog version="4.2.0"] : 4: CamTER - CAMID already set - ignore get camid
- </pre>
- Der Aufbau der Payload unterscheidet sich je nach verwendeten logFormat. <br><br>
-
- <b>logFormat IETF:</b> <br><br>
- "<PRIVAL>IETFVERS TIME MYHOST IDENT PID MID [SD-FIELD] 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> IETFVERS </td><td> Version der benutzten RFC5424 Spezifikation </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>
- </table>
- </ul>
- <br>
-
- <b>logFormat BSD:</b> <br><br>
- "<PRIVAL>MONTH DAY TIME MYHOST IDENT[PID]: 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> MONTH </td><td> Monatsangabe nach RFC3164 </td></tr>
- <tr><td> DAY </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> TAG </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> Die ID der Mitteilung (= Sequenznummer) </td></tr>
- <tr><td> MESSAGE </td><td> der zu übertragende Datensatz </td></tr>
- </table>
- </ul>
- <br>
-
- </ul>
- <br><br>
-
- <a name="Log2SyslogSet"></a>
- <b>Set</b>
- <ul>
- <br>
-
- <ul>
- <li><b>reopen </b><br>
- <br>
- Schließt eine bestehende Client/Server-Verbindung und öffnet sie erneut.
- Der Befehl kann z.B. bei "broken pipe"-Fehlern hilfreich sein.
- </li>
- </ul>
- <br>
-
- <ul>
- <li><b>sendTestMessage [<Message>] </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 <Message> 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>
-
- <a name="Log2SyslogGet"></a>
- <b>Get</b>
- <ul>
- <br>
-
- <ul>
- <li><b>certinfo </b><br>
- <br>
- Zeigt auf einem Sender-Device Informationen zum Serverzertifikat an sofern eine TLS-Session aufgebaut wurde
- (Reading "SSL_Version" ist nicht "n.a.").
- </li>
- </ul>
- <br>
-
- <ul>
- <li><b>versionNotes </b><br>
- <br>
- Zeigt Release Informationen und Hinweise zum Modul an. Es sind nur Informationen mit Bedeutung für den Modulnutzer
- enthalten.
- </li>
- </ul>
- <br>
- </ul>
- <br>
-
- <a name="Log2Syslogattr"></a>
- <b>Attribute</b>
- <ul>
- <br>
-
- <ul>
- <a name="addTimestamp"></a>
- <li><b>addTimestamp </b><br>
- <br/>
- 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>
- Die Einstellung kann hilfeich sein wenn mseclog in FHEM aktiviert ist.<br>
- <br/>
-
- Beispielausgabe (raw) eines Splunk Syslog Servers:<br/>
- <pre>Aug 18 21:26:55 fhemtest.myds.me 1 2017-08-18T21: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-18T21: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-18T21:26:54 fhemtest.myds.me Test_event 13339 FHEM - : 2017-08-18 21:26:54 recalc_Bezug state: Next: 21:31:59
- </pre>
- </li>
- </ul>
- <br>
- <ul>
- <a name="addStateEvent"></a>
- <li><b>addStateEvent </b><br>
- <br>
- Das Attribut ist nur für "Sender" verwendbar. Wenn gesetzt, werden state-events mit dem Reading "state" ergänzt.<br>
- Die Standardeinstellung ist ohne state-Ergänzung.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="contDelimiter"></a>
- <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>
-
- <ul>
- <a name="disable"></a>
- <li><b>disable [1 | 0 | maintenance] </b><br>
- <br>
- 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").
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="logFormat"></a>
- <li><b>logFormat [ BSD | IETF ]</b><br>
- <br>
- Das Attribut ist nur für "Sender" verwendbar. Es stellt das Protokollformat ein. (default: "IETF") <br>
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="makeEvent"></a>
- <li><b>makeEvent [ intern | no | reading ]</b><br>
- <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> Events werden modulintern generiert und sind nur im Eventmonitor sichtbar. Readings werden nicht erstellt. </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>
-
- <ul>
- <a name="octetCount"></a>
- <li><b>octetCount </b><br>
- <br>
- Das Attribut ist nur für "Sender" verfügbar. <br>
- Wenn gesetzt, wird das Syslog Framing von Non-Transparent-Framing (default) in Octet-Framing geändert.
- Der Syslog-Empfänger muss Octet-Framing unterstützen !
- Für weitere Informationen siehe RFC6587 <a href="https://tools.ietf.org/html/rfc6587">"Transmission of Syslog Messages
- over TCP"</a>.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="outputFields"></a>
- <li><b>outputFields </b><br>
- <br>
- Das Attribut ist nur für "Collector" verwendbar.
- Über eine sortierbare Liste können die gewünschten Felder des generierten Events ausgewählt werden.
- 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>
- <a name="parseFn"></a>
- <li><b>parseFn {<Parsefunktion>} </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>
- <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>
- <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>
- <tr><td> $IGNORE </td><td> 0 (0|1), wenn $IGNORE==1 wird der Syslog-Datensatz ignoriert </td></tr>
- </table>
- </ul>
- <br>
- Die Variablennamen korrespondieren mit den Feldnamen und deren ursprünglicher Bedeutung angegeben im Attribut
- <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>
-
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="parseProfile"></a>
- <li><b>parseProfile [ BSD | IETF | ... | ParseFn | raw ] </b><br>
- <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>
- <tr><td> <b>...</b> </td><td> Es werden weitere angepasste Parsingprofile für ausgewählte Geräte angeboten </td></tr>
- <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>
- <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>
- </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>
- <br>
-
- <ul>
- <a name="port"></a>
- <li><b>port <Port></b><br>
- <br>
- 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>
-
- <ul>
- <a name="protocol"></a>
- <li><b>protocol [ TCP | UDP ]</b><br>
- <br>
- Setzt den Protokolltyp der verwendet werden soll. Es kann UDP oder TCP gewählt werden. <br>
- Standard ist "UDP" wenn nichts spezifiziert ist.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="rateCalcRerun"></a>
- <li><b>rateCalcRerun <Zeit in Sekunden> </b><br>
- <br>
- 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.
- Default sind 60 Sekunden.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="respectSeverity"></a>
- <li><b>respectSeverity </b><br>
- <br>
- 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.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="sslCertPrefix"></a>
- <li><b>sslCertPrefix</b><br>
- <br>
- Setzt das Präfix der SSL-Zertifikate, die Voreinstellung ist "certs/server-".
- Mit diesem Attribut kann für verschiedene Log2Syslog-Devices die Verwendung unterschiedlicher SSL-Zertifikate
- bestimmt werden.
- Siehe auch das "TLS" Attribut.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="ssldebug"></a>
- <li><b>ssldebug</b><br>
- <br>
- Debugging Level von SSL Messages. Das Attribut ist nur für Device-MODEL "Sender" verwendbar. <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 Fortschrittinformationen 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>
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="TLS"></a>
- <li><b>TLS</b><br>
- <br>
- Ein Client (Sender) baut eine gesicherte Verbindung zum Syslog-Server auf.
- Ein Syslog-Server (Collector) stellt eine gesicherte Verbindung zur Verfügung.
- Das Protokoll schaltet automatisch auf TCP um.
- <br<br>
-
- Damit ein Collector TLS verwenden kann, muss ein Zertifikat erstellt werden bzw. vorhanden sein.
- Mit folgenden Schritten kann ein Zertifikat erzeugt werden: <br><br>
-
- 1. im FHEM-Basisordner das Verzeichnis "certs" anlegen: <br>
- <pre>
- sudo mkdir /opt/fhem/certs
- </pre>
-
- 2. SSL Zertifikat erstellen: <br>
- <pre>
- cd /opt/fhem/certs
- sudo openssl req -new -x509 -nodes -out server-cert.pem -days 3650 -keyout server-key.pem
- </pre>
-
- 3. Datei/Verzeichnis-Rechte setzen: <br>
- <pre>
- sudo chown -R fhem:dialout /opt/fhem/certs
- sudo chmod 644 /opt/fhem/certs/*.pem
- sudo chmod 711 /opt/fhem/certs
- </pre>
-
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="timeout"></a>
- <li><b>timeout</b><br>
- <br>
- Das Attribut ist nur für "Sender" verwendbar.
- Timeout für die Verbindung zum Syslog-Server (TCP). Default: 0.5s.
- </li>
- </ul>
- <br>
- <br>
-
- <ul>
- <a name="verbose"></a>
- <li><b>verbose</b><br>
- <br>
- Verbose-Level entsprechend dem globalen <a href="#attributes">Attribut</a> "verbose".
- Die Ausgaben der Verbose-Level von Log2Syslog-Devices werden ausschließlich im lokalen FHEM Logfile ausgegeben und
- nicht weitergeleitet um Schleifen zu vermeiden.
- </li>
- </ul>
- <br>
- <br>
-
- </ul>
- <br>
-
- <a name="Log2Syslogreadings"></a>
- <b>Readings</b>
- <ul>
- <br>
- <table>
- <colgroup> <col width=35%> <col width=65%> </colgroup>
- <tr><td><b>MSG_<Host></b> </td><td> die letzte erfolgreich geparste Syslog-Message von <Host> </td></tr>
- <tr><td><b>Parse_Err_No</b> </td><td> die Anzahl der Parse-Fehler seit Start </td></tr>
- <tr><td><b>SSL_Algorithm</b> </td><td> der verwendete SSL Algorithmus wenn SSL eingeschaltet und aktiv ist </td></tr>
- <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>
- </table>
- <br>
- </ul>
-
- </ul>
- =end html_DE
- =cut
|