source: nscp/modules/CheckEventLog/CheckEventLog.cpp @ 98113da

0.4.00.4.10.4.2
Last change on this file since 98113da was 98113da, checked in by Michael Medin <michael@…>, 20 months ago
  • Real-time CheckEventLog working (still only for one, and I think application log)
  • Added python tests to validfate that Real-time eventlog is working.
  • Fixed som defects here and there (now builds on Linux again)
  • Fixed so it builds in "debug mode"
  • Fixed issue in grammar which caused infiniate loop in som cases
  • Fixed so error rendering in eventlog works with "infininate number of argumnets"
  • Added support for targeting execs (in API)
  • Fixed some invalid return messages
  • Streamlined submissions wrappers to be more inline with "other wrappers"
  • Fixed a myrriad of minor python script bugs
  • Added sleep command (which sometimes causes issues so use with care)
  • Property mode set to 100644
File size: 25.0 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21
22#include "stdafx.h"
23#include "CheckEventLog.h"
24#include <filter_framework.hpp>
25#include <boost/foreach.hpp>
26
27#include <time.h>
28#include <utils.h>
29#include <error.hpp>
30#include <map>
31#include <vector>
32//#include <config.h>
33
34#include <boost/bind.hpp>
35#include <boost/assign.hpp>
36#include <boost/program_options.hpp>
37
38#include "filter.hpp"
39
40#include <nscapi/functions.hpp>
41
42#include <parsers/where/unary_fun.hpp>
43#include <parsers/where/list_value.hpp>
44#include <parsers/where/binary_op.hpp>
45#include <parsers/where/unary_op.hpp>
46#include <parsers/where/variable.hpp>
47
48#include <simple_timer.hpp>
49#include <settings/client/settings_client.hpp>
50namespace sh = nscapi::settings_helper;
51
52#include "simple_registry.hpp"
53#include "eventlog_record.hpp"
54
55CheckEventLog::CheckEventLog() {
56}
57CheckEventLog::~CheckEventLog() {
58}
59struct parse_exception {
60        parse_exception(std::wstring) {}
61};
62
63
64bool CheckEventLog::loadModule() {
65        return false;
66}
67
68WORD get_language(std::string lang) {
69        if (lang == "neutral") return LANG_NEUTRAL;
70        if (lang == "arabic") return LANG_ARABIC;
71        if (lang == "bulgarian") return LANG_BULGARIAN;
72        if (lang == "catalan") return LANG_CATALAN;
73        if (lang == "chinese") return LANG_CHINESE;
74        if (lang == "czech") return LANG_CZECH;
75        if (lang == "danish") return LANG_DANISH;
76        if (lang == "german") return LANG_GERMAN;
77        if (lang == "greek") return LANG_GREEK;
78        if (lang == "english") return LANG_ENGLISH;
79        if (lang == "spanish") return LANG_SPANISH;
80        if (lang == "finnish") return LANG_FINNISH;
81        if (lang == "french") return LANG_FRENCH;
82        if (lang == "hebrew") return LANG_HEBREW;
83        if (lang == "hungarian") return LANG_HUNGARIAN;
84        if (lang == "icelandic") return LANG_ICELANDIC;
85        if (lang == "italian") return LANG_ITALIAN;
86        if (lang == "japanese") return LANG_JAPANESE;
87        if (lang == "korean") return LANG_KOREAN;
88        if (lang == "dutch") return LANG_DUTCH;
89        if (lang == "norwegian") return LANG_NORWEGIAN;
90        if (lang == "polish") return LANG_POLISH;
91        if (lang == "portuguese") return LANG_PORTUGUESE;
92        if (lang == "romanian") return LANG_ROMANIAN;
93        if (lang == "russian") return LANG_RUSSIAN;
94        if (lang == "croatian") return LANG_CROATIAN;
95        if (lang == "serbian") return LANG_SERBIAN;
96        if (lang == "slovak") return LANG_SLOVAK;
97        if (lang == "albanian") return LANG_ALBANIAN;
98        if (lang == "swedish") return LANG_SWEDISH;
99        if (lang == "thai") return LANG_THAI;
100        if (lang == "turkish") return LANG_TURKISH;
101        if (lang == "urdu") return LANG_URDU;
102        if (lang == "indonesian") return LANG_INDONESIAN;
103        if (lang == "ukrainian") return LANG_UKRAINIAN;
104        if (lang == "belarusian") return LANG_BELARUSIAN;
105        if (lang == "slovenian") return LANG_SLOVENIAN;
106        if (lang == "estonian") return LANG_ESTONIAN;
107        if (lang == "latvian") return LANG_LATVIAN;
108        if (lang == "lithuanian") return LANG_LITHUANIAN;
109        if (lang == "farsi") return LANG_FARSI;
110        if (lang == "vietnamese") return LANG_VIETNAMESE;
111        if (lang == "armenian") return LANG_ARMENIAN;
112        if (lang == "azeri") return LANG_AZERI;
113        if (lang == "basque") return LANG_BASQUE;
114        if (lang == "macedonian") return LANG_MACEDONIAN;
115        if (lang == "afrikaans") return LANG_AFRIKAANS;
116        if (lang == "georgian") return LANG_GEORGIAN;
117        if (lang == "faeroese") return LANG_FAEROESE;
118        if (lang == "hindi") return LANG_HINDI;
119        if (lang == "malay") return LANG_MALAY;
120        if (lang == "kazak") return LANG_KAZAK;
121        if (lang == "kyrgyz") return LANG_KYRGYZ;
122        if (lang == "swahili") return LANG_SWAHILI;
123        if (lang == "uzbek") return LANG_UZBEK;
124        if (lang == "tatar") return LANG_TATAR;
125        if (lang == "punjabi") return LANG_PUNJABI;
126        if (lang == "gujarati") return LANG_GUJARATI;
127        if (lang == "tamil") return LANG_TAMIL;
128        if (lang == "telugu") return LANG_TELUGU;
129        if (lang == "kannada") return LANG_KANNADA;
130        if (lang == "marathi") return LANG_MARATHI;
131        if (lang == "sanskrit") return LANG_SANSKRIT;
132        if (lang == "mongolian") return LANG_MONGOLIAN;
133        if (lang == "galician") return LANG_GALICIAN;
134        if (lang == "konkani") return LANG_KONKANI;
135        if (lang == "syriac") return LANG_SYRIAC;
136        if (lang == "divehi") return LANG_DIVEHI;
137        return LANG_NEUTRAL;
138}
139
140void real_time_thread::set_language(std::string lang) {
141        WORD wLang = get_language(lang);
142        if (wLang == LANG_NEUTRAL)
143                info.dwLang = MAKELANGID(wLang, SUBLANG_DEFAULT);
144        else
145                info.dwLang = MAKELANGID(wLang, SUBLANG_NEUTRAL);
146}
147
148
149/*
150void process_event(eventlog_filter::filter_engine engine, eventlog_filter::filter_argument fargs, const EVENTLOGRECORD* record) {
151
152        __time64_t ltime;
153        _time64(&ltime);
154
155        EventLogRecord elr(_T("application"), record, ltime);
156        ;
157        //boost::shared_ptr<eventlog_filter::filter_obj> arg = boost::shared_ptr<eventlog_filter::filter_obj>(new eventlog_filter::filter_obj(record));
158        boost::shared_ptr<eventlog_filter::filter_obj> arg = boost::shared_ptr<eventlog_filter::filter_obj>(new eventlog_filter::filter_obj(elr));
159
160        if (engine->match(arg)) {
161                NSC_DEBUG_MSG(_T("Found record: ") + elr.render(true, fargs->syntax));
162
163        } else {
164                NSC_DEBUG_MSG(_T("Ignored record: ") + elr.render(true, fargs->syntax));
165        }
166}
167*/
168void real_time_thread::process_no_events() {
169        std::wstring response;
170        if (!GET_CORE()->submit_simple_message(info.target, info.alias, NSCAPI::returnCRIT, info.ok_msg, info.perf_msg, response)) {
171                NSC_LOG_ERROR(_T("Failed to submit evenhtlog result: ") + response);
172        }
173}
174
175void real_time_thread::process_record(const EventLogRecord &record) {
176        std::wstring response;
177        std::wstring message = record.render(true, info.syntax, DATE_FORMAT, info.dwLang);
178        NSC_LOG_ERROR(_T("XXX: ") + message);
179        if (!GET_CORE()->submit_simple_message(info.target, info.alias, NSCAPI::returnCRIT, message, info.perf_msg, response)) {
180                NSC_LOG_ERROR(_T("Failed to submit evenhtlog result: ") + response);
181        }
182}
183
184void real_time_thread::thread_proc() {
185        if (filters_.size() != 1) {
186                NSC_LOG_ERROR_STD(_T("Invalid filter size (for now)..."));
187                return;
188        }
189
190        eventlog_filter::filter_argument fargs = eventlog_filter::factories::create_argument(info.syntax, DATE_FORMAT);
191        fargs->filter = *filters_.begin();
192        fargs->debug = true;
193        eventlog_filter::filter_engine engine = eventlog_filter::factories::create_engine(fargs);
194
195
196
197        if (!engine) {
198                NSC_LOG_ERROR_STD(_T("No filter subsystem available"));
199                return;
200        }
201
202        if (!engine->boot()) {
203                NSC_LOG_ERROR_STD(_T("Error booting filters"));
204                return;
205        }
206
207        std::wstring message;
208        if (!engine->validate(message)) {
209                NSC_LOG_ERROR_STD(_T("Error validating session: ") + message);
210                return;
211        }
212
213        eventlog_wrapper eventlog(_T("application"));
214        // TODO: add support for "multiple" eventlogs and configurable event logs
215
216        // TODO: add support for scanning "missed messages" at startup
217
218        if (!eventlog.seek_end()) {
219                NSC_LOG_ERROR_STD(_T("Failed to find the end of the eventlog"));
220                return;
221        }
222
223        HANDLE handles[2];
224        handles[1] = stop_event_;
225
226        eventlog.notify(handles[0]);
227
228        DWORD dwWaitTime = max_age_;
229        if (dwWaitTime > 0 && dwWaitTime < 5000)
230                dwWaitTime = 5000;
231        unsigned int errors = 0;
232        while (true) {
233                DWORD dwWaitReason = WaitForMultipleObjects(sizeof(handles)/sizeof(HANDLE), handles, FALSE, dwWaitTime==0?INFINITE:dwWaitTime);
234               
235                if (dwWaitReason == WAIT_TIMEOUT) {
236                        process_no_events();
237                } else if (dwWaitReason == WAIT_OBJECT_0) {
238
239                        DWORD status = eventlog.read_record(0, EVENTLOG_SEQUENTIAL_READ|EVENTLOG_FORWARDS_READ);
240                        if (ERROR_SUCCESS != status && ERROR_HANDLE_EOF != status)
241                                return;
242
243                        __time64_t ltime;
244                        _time64(&ltime);
245
246                        EVENTLOGRECORD *pevlr = eventlog.read_record_with_buffer();
247                        while (pevlr != NULL) {
248                                EventLogRecord elr(eventlog.get_name(), pevlr, ltime);
249                                boost::shared_ptr<eventlog_filter::filter_obj> arg = boost::shared_ptr<eventlog_filter::filter_obj>(new eventlog_filter::filter_obj(elr));
250
251                                if (engine->match(arg)) {
252                                        process_record(elr);
253                                } else if (fargs->debug) {
254                                        NSC_DEBUG_MSG(_T("Ignored record: ") + elr.render(true, fargs->syntax));
255                                }
256                                pevlr = eventlog.read_record_with_buffer();
257                        }
258                } else if (dwWaitReason == WAIT_OBJECT_0 + 1) {
259                        return;
260                } else {
261                        NSC_LOG_ERROR(_T("Error failed to wait for eventlog message: ") + error::lookup::last_error());
262                        if (errors > 10) {
263                                NSC_LOG_ERROR(_T("To many errors giving up"));
264                                return;
265                        }
266                }
267        }
268}
269
270
271bool real_time_thread::start() {
272        if (!enabled_)
273                return true;
274        if (!has_filters()) {
275                add_realtime_filter(_T("default"), _T("type NOT IN ('success', 'info', 'auditSuccess')"));
276        }
277
278        stop_event_ = CreateEvent(NULL, TRUE, FALSE, _T("EVentLogShutdown"));
279
280        thread_ = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&real_time_thread::thread_proc, this)));
281        return true;
282}
283bool real_time_thread::stop() {
284        SetEvent(stop_event_);
285        if (thread_)
286                thread_->join();
287        return true;
288}
289
290void real_time_thread::add_realtime_filter(std::wstring key, std::wstring query) {
291        if (!key.empty() && query.empty())
292                filters_.push_back(key);
293        else
294                filters_.push_back(query);
295}
296
297
298bool CheckEventLog::loadModuleEx(std::wstring alias, NSCAPI::moduleLoadMode mode) {
299        try {
300                register_command(_T("CheckEventLog"), _T("Check for errors in the event logger!"));
301                register_command(_T("check_event_log"), _T("Check for errors in the event logger!"));
302                register_command(_T("check_eventlog"), _T("Check for errors in the event logger!"));
303
304                sh::settings_registry settings(get_settings_proxy());
305                settings.set_alias(alias, _T("eventlog"));
306
307                settings.alias().add_path_to_settings()
308                        (_T("EVENT LOG SECTION"), _T("Section for the EventLog Checker (CheckEventLog.dll)."))
309
310                        (_T("real-time"), _T("CONFIGURE REALTIME CHECKING"), _T("A set of options to configure the real time checks"))
311
312                        (_T("real-time/filters"), sh::fun_values_path(boost::bind(&real_time_thread::add_realtime_filter, thread_, _1, _2)), 
313                        _T("REALTIME FILTERS"), _T("A set of filters to use in real-time mode"))
314                        ;
315
316                settings.alias().add_key_to_settings()
317                        (_T("debug"), sh::bool_key(&debug_, false),
318                        _T("DEBUG"), _T("Log more information when filtering (usefull to detect issues with filters) not usefull in production as it is a bit of a resource hog."))
319
320                        (_T("lookup names"), sh::bool_key(&lookup_names_, true),
321                        _T("LOOKUP NAMES"), _T("Lookup the names of eventlog files"))
322
323                        (_T("syntax"), sh::wstring_key(&syntax_),
324                        _T("SYNTAX"), _T("Set this to use a specific syntax string for all commands (that don't specify one)."))
325
326                        (_T("buffer size"), sh::int_key(&buffer_length_, 128*1024),
327                        _T("BUFFER_SIZE"), _T("The size of the buffer to use when getting messages this affects the speed and maximum size of messages you can recieve."))
328
329                        ;
330
331                settings.alias().add_key_to_settings(_T("real-time"))
332
333                        (_T("enabled"), sh::bool_fun_key<bool>(boost::bind(&real_time_thread::set_enabled, &thread_, _1), false),
334                        _T("REAL TIME CHECKING"), _T("Spawns a backgrounnd thread which detects issues and reports them back instantly."))
335
336                        (_T("destination"), sh::string_fun_key<std::wstring>(boost::bind(&real_time_thread::set_destination, &thread_, _1), _T("NSCA")),
337                        _T("DESTINATION"), _T("The destination for intercepted messages"))
338
339                        (_T("startup age"), sh::string_fun_key<std::wstring>(boost::bind(&real_time_thread::set_start_age, &thread_, _1), _T("30m")),
340                        _T("STARTUP AGE"), _T("The initial age to scan when starting NSClient++"))
341
342                        (_T("maximum age"), sh::string_fun_key<std::wstring>(boost::bind(&real_time_thread::set_max_age, &thread_, _1), _T("5m")),
343                        _T("MAGIMUM AGE"), _T("How long befor reporting \"ok\" (if this is set to off no ok will be reported only errors)"))
344
345                        (_T("filter"), sh::string_fun_key<std::wstring>(boost::bind(&real_time_thread::set_filter, &thread_, _1), _T("")),
346                        _T("STARTUP AGE"), _T("The initial age to scan when starting NSClient++"))
347
348                        (_T("syntax"), sh::wstring_key(&thread_.info.syntax, _T("%type% %source%: %message%")),
349                        _T("STARTUP AGE"), _T("The initial age to scan when starting NSClient++"))
350
351                        (_T("language"), sh::string_fun_key<std::string>(boost::bind(&real_time_thread::set_language, &thread_, _1), ""),
352                        _T("MESSAGE LANGUAGE"), _T("The language to use for rendering message (mainly used fror testing)"))
353
354                        ;
355
356                settings.register_all();
357                settings.notify();
358
359                if (mode == NSCAPI::normalStart) {
360                        if (!thread_.start())
361                                NSC_LOG_ERROR_STD(_T("Failed to start collection thread"));
362                }
363
364        } catch (nscapi::nscapi_exception &e) {
365                NSC_LOG_ERROR_STD(_T("Failed to register command: ") + utf8::cvt<std::wstring>(e.what()));
366                return false;
367        } catch (std::exception &e) {
368                NSC_LOG_ERROR_STD(_T("Exception: ") + utf8::cvt<std::wstring>(e.what()));
369                return false;
370        } catch (...) {
371                NSC_LOG_ERROR_STD(_T("Failed to register command."));
372                return false;
373        }
374        return true;
375}
376bool CheckEventLog::unloadModule() {
377        if (!thread_.stop())
378                NSC_LOG_ERROR_STD(_T("Failed to start collection thread"));
379        return true;
380}
381
382bool CheckEventLog::hasCommandHandler() {
383        return true;
384}
385bool CheckEventLog::hasMessageHandler() {
386        return false;
387}
388
389class uniq_eventlog_record {
390        DWORD ID;
391        WORD type;
392        WORD category;
393public:
394        std::wstring message;
395        uniq_eventlog_record(EVENTLOGRECORD *pevlr) : ID(pevlr->EventID&0xffff), type(pevlr->EventType), category(pevlr->EventCategory) {}
396        bool operator< (const uniq_eventlog_record &other) const {
397                return (ID < other.ID) || ((ID==other.ID)&&(type < other.type)) || (ID==other.ID&&type==other.type)&&(category < other.category);
398        }
399        std::wstring to_string() const {
400                return _T("id=") + strEx::itos(ID) + _T("type=") + strEx::itos(type) + _T("category=") + strEx::itos(category);
401        }
402};
403typedef std::map<uniq_eventlog_record,unsigned int> uniq_eventlog_map;
404
405struct event_log_buffer {
406        BYTE *bBuffer;
407        DWORD bufferSize_;
408        event_log_buffer(DWORD bufferSize) : bufferSize_(bufferSize) {
409                bBuffer = new BYTE[bufferSize+10];
410        }
411        ~event_log_buffer() {
412                delete [] bBuffer;
413        }
414        EVENTLOGRECORD* getBufferUnsafe() {
415                return reinterpret_cast<EVENTLOGRECORD*>(bBuffer);
416        }
417        DWORD getBufferSize() {
418                return bufferSize_;
419        }
420};
421
422NSCAPI::nagiosReturn CheckEventLog::handleCommand(const std::wstring &target, const std::wstring &command, std::list<std::wstring> &arguments, std::wstring &message, std::wstring &perf) {
423        if (command != _T("checkeventlog"))
424                return NSCAPI::returnIgnored;
425        simple_timer time;
426        typedef checkHolders::CheckContainer<checkHolders::MaxMinBoundsULongInteger> EventLogQuery1Container;
427        typedef checkHolders::CheckContainer<checkHolders::ExactBoundsULongInteger> EventLogQuery2Container;
428       
429        NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK;
430
431        std::list<std::wstring> files;
432        EventLogQuery1Container query1;
433        EventLogQuery2Container query2;
434
435
436        eventlog_filter::filter_argument fargs = eventlog_filter::factories::create_argument(syntax_, DATE_FORMAT);
437
438        bool bPerfData = true;
439        bool unique = false;
440        unsigned int truncate = 0;
441        event_log_buffer buffer(buffer_length_);
442        //bool bPush = true;
443
444        try {
445                MAP_OPTIONS_BEGIN(arguments)
446                        MAP_OPTIONS_NUMERIC_ALL(query1, _T(""))
447                        MAP_OPTIONS_EXACT_NUMERIC_ALL(query2, _T(""))
448                        MAP_OPTIONS_STR2INT(_T("truncate"), truncate)
449                        MAP_OPTIONS_BOOL_TRUE(_T("unique"), unique)
450                        MAP_OPTIONS_BOOL_TRUE(_T("descriptions"), fargs->bShowDescriptions)
451                        MAP_OPTIONS_PUSH(_T("file"), files)
452                        MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData)
453                        MAP_OPTIONS_BOOL_EX(_T("filter"), fargs->bFilterIn, _T("in"), _T("out"))
454                        MAP_OPTIONS_BOOL_EX(_T("filter"), fargs->bFilterAll, _T("all"), _T("any"))
455                        MAP_OPTIONS_BOOL_EX(_T("debug"), fargs->debug, _T("true"), _T("false"))
456                        MAP_OPTIONS_STR(_T("syntax"), fargs->syntax)
457                        MAP_OPTIONS_STR(_T("filter"), fargs->filter)
458                        MAP_OPTIONS_MISSING(message, _T("Unknown argument: "))
459                        MAP_OPTIONS_END()
460        } catch (filters::parse_exception e) {
461                message = e.getMessage();
462                return NSCAPI::returnUNKNOWN;
463        } catch (filters::filter_exception e) {
464                message = e.getMessage();
465                return NSCAPI::returnUNKNOWN;
466                } catch (checkHolders::parse_exception e) {
467                message = e.getMessage();
468                return NSCAPI::returnUNKNOWN;
469        } catch (...) {
470                message = _T("Invalid command line!");
471                return NSCAPI::returnUNKNOWN;
472        }
473
474        unsigned long int hit_count = 0;
475        if (files.empty()) {
476                message = _T("No file specified try adding: file=Application");
477                return NSCAPI::returnUNKNOWN;
478        }
479        bool buffer_error_reported = false;
480
481
482        eventlog_filter::filter_engine impl = eventlog_filter::factories::create_engine(fargs);
483
484        if (!impl) {
485                message = _T("Failed to initialize filter subsystem.");
486                return NSCAPI::returnUNKNOWN;
487        }
488
489        impl->boot();
490
491        __time64_t ltime;
492        _time64(&ltime);
493
494        if (!impl->validate(message)) {
495                return NSCAPI::returnUNKNOWN;
496        }
497
498
499        NSC_DEBUG_MSG_STD(_T("Boot time: ") + strEx::itos(time.stop()));
500
501        for (std::list<std::wstring>::const_iterator cit2 = files.begin(); cit2 != files.end(); ++cit2) {
502                std::wstring name = *cit2;
503                if (lookup_names_) {
504                        name = eventlog_wrapper::find_eventlog_name(*cit2);
505                        if ((*cit2) != name) {
506                                NSC_DEBUG_MSG_STD(_T("Opening alternative log: ") + name);
507                        }
508                }
509                HANDLE hLog = OpenEventLog(NULL, name.c_str());
510                if (hLog == NULL) {
511                        message = _T("Could not open the '") + (*cit2) + _T("' event log: ") + error::lookup::last_error();
512                        return NSCAPI::returnUNKNOWN;
513                }
514                uniq_eventlog_map uniq_records;
515
516                DWORD dwRead, dwNeeded;
517                while (true) {
518                        BOOL bStatus = ReadEventLog(hLog, EVENTLOG_FORWARDS_READ|EVENTLOG_SEQUENTIAL_READ,
519                                0, buffer.getBufferUnsafe(), buffer.getBufferSize(), &dwRead, &dwNeeded);
520                        if (bStatus == FALSE) {
521                                DWORD err = GetLastError();
522                                if (err == ERROR_INSUFFICIENT_BUFFER) {
523                                        if (!buffer_error_reported) {
524                                                NSC_LOG_ERROR_STD(_T("EvenlogBuffer is too small change the value of buffer_length=") + strEx::itos(dwNeeded+1) + _T(": ") + error::lookup::last_error(err));
525                                                buffer_error_reported = true;
526                                        }
527                                } else if (err == ERROR_HANDLE_EOF) {
528                                        break;
529                                } else {
530                                        NSC_LOG_ERROR_STD(_T("Failed to read from eventlog: ") + error::lookup::last_error(err));
531                                        message = _T("Failed to read from eventlog: ") + error::lookup::last_error(err);
532                                        CloseEventLog(hLog);
533                                        return NSCAPI::returnUNKNOWN;
534                                }
535                        }
536                        EVENTLOGRECORD *pevlr = buffer.getBufferUnsafe();
537                        while (dwRead > 0) {
538                                EventLogRecord record((*cit2), pevlr, ltime);
539                                boost::shared_ptr<eventlog_filter::filter_obj> arg = boost::shared_ptr<eventlog_filter::filter_obj>(new eventlog_filter::filter_obj(record));
540                                bool match = impl->match(arg);
541                                if (match&&unique) {
542                                        match = false;
543                                        uniq_eventlog_record uniq_record = pevlr;
544                                        uniq_eventlog_map::iterator it = uniq_records.find(uniq_record);
545                                        if (it != uniq_records.end()) {
546                                                (*it).second ++;
547                                        }
548                                        else {
549                                                if (!fargs->syntax.empty()) {
550                                                        uniq_record.message = record.render(fargs->bShowDescriptions, fargs->syntax);
551                                                } else if (!fargs->bShowDescriptions) {
552                                                        uniq_record.message = record.eventSource();
553                                                } else {
554                                                        uniq_record.message = record.eventSource();
555                                                        uniq_record.message += _T("(") + EventLogRecord::translateType(record.eventType()) + _T(", ") +
556                                                                strEx::itos(record.eventID()) + _T(", ") + EventLogRecord::translateSeverity(record.severity()) + _T(")");
557                                                        uniq_record.message += _T("[") + record.enumStrings() + _T("]");
558                                                        uniq_record.message += _T("{%count%}");
559                                                }
560                                                uniq_records[uniq_record] = 1;
561                                        }
562                                        hit_count++;
563                                } else if (match) {
564                                        if (!fargs->syntax.empty()) {
565                                                strEx::append_list(message, record.render(fargs->bShowDescriptions, fargs->syntax));
566                                        } else if (!fargs->bShowDescriptions) {
567                                                strEx::append_list(message, record.eventSource());
568                                        } else {
569                                                strEx::append_list(message, record.eventSource());
570                                                message += _T("(") + EventLogRecord::translateType(record.eventType()) + _T(", ") +
571                                                        strEx::itos(record.eventID()) + _T(", ") + EventLogRecord::translateSeverity(record.severity()) + _T(")");
572                                                message += _T("[") + record.enumStrings() + _T("]");
573                                        }
574                                        hit_count++;
575                                }
576                                dwRead -= pevlr->Length;
577                                pevlr = reinterpret_cast<EVENTLOGRECORD*>((LPBYTE)pevlr + pevlr->Length);
578                        }
579                }
580                CloseEventLog(hLog);
581                for (uniq_eventlog_map::const_iterator cit = uniq_records.begin(); cit != uniq_records.end(); ++cit) {
582                        std::wstring msg = (*cit).first.message;
583                        strEx::replace(msg, _T("%count%"), strEx::itos((*cit).second));
584                        strEx::append_list(message, msg);
585                }
586        }
587        NSC_DEBUG_MSG_STD(_T("Evaluation time: ") + strEx::itos(time.stop()));
588
589        if (!bPerfData) {
590                query1.perfData = false;
591                query2.perfData = false;
592        }
593        if (query1.alias.empty())
594                query1.alias = _T("eventlog");
595        if (query2.alias.empty())
596                query2.alias = _T("eventlog");
597        if (query1.hasBounds())
598                query1.runCheck(hit_count, returnCode, message, perf);
599        else if (query2.hasBounds())
600                query2.runCheck(hit_count, returnCode, message, perf);
601        else {
602                message = _T("No bounds specified!");
603                return NSCAPI::returnUNKNOWN;
604        }
605        if ((truncate > 0) && (message.length() > (truncate-4)))
606                message = message.substr(0, truncate-4) + _T("...");
607        if (message.empty())
608                message = _T("Eventlog check ok");
609        return returnCode;
610}
611NSCAPI::nagiosReturn CheckEventLog::commandRAWLineExec(const wchar_t* char_command, const std::string &request, std::string &response) {
612        std::wstring command = char_command;
613        if (command == _T("insert-eventlog-message") || command == _T("insert-eventlog") || command == _T("insert-message")) {
614                nscapi::functions::decoded_simple_command_data data = nscapi::functions::parse_simple_exec_request(char_command, request);
615                std::wstring message;
616                std::vector<std::wstring> args(data.args.begin(), data.args.end());
617                bool ok = insert_eventlog(args, message);
618                nscapi::functions::create_simple_exec_response(command, ok?NSCAPI::isSuccess:NSCAPI::hasFailed, message, response);
619                return ok?NSCAPI::isSuccess:NSCAPI::hasFailed;
620        }
621        return NSCAPI::returnIgnored;
622}
623
624
625
626NSCAPI::nagiosReturn CheckEventLog::insert_eventlog(std::vector<std::wstring> arguments, std::wstring &message) {
627        try {
628                namespace po = boost::program_options;
629
630                bool help = false;
631                std::wstring type, category, severity, source_name;
632                std::vector<std::wstring> strings;
633                WORD wEventID;
634                po::options_description desc("Allowed options");
635                desc.add_options()
636                        ("help,h", po::bool_switch(&help), "Show help screen")
637                        ("source,s", po::wvalue<std::wstring>(&source_name)->default_value(_T("Application Error")), "source to use")
638                        ("type,t", po::wvalue<std::wstring>(&type), "Event type")
639                        ("severity", po::wvalue<std::wstring>(&severity), "Event severity")
640                        ("category,c", po::wvalue<std::wstring>(&category), "Event category")
641                        ("arguments,a", po::wvalue<std::vector<std::wstring> >(&strings), "Message arguments (strings)")
642                        ("id,i", po::value<WORD>(&wEventID), "Event ID")
643                        ;
644
645                boost::program_options::variables_map vm;
646
647                po::wparsed_options parsed = po::basic_command_line_parser<wchar_t>(arguments).options(desc).run();
648                po::store(parsed, vm);
649                po::notify(vm);
650
651                if (help) {
652                        std::stringstream ss;
653                        ss << "CheckEventLog Command line syntax:" << std::endl;
654                        ss << desc;
655                        message = utf8::cvt<std::wstring>(ss.str());
656                        return NSCAPI::isSuccess;
657                } else {
658                        event_source source(source_name);
659                        WORD dwType = EventLogRecord::translateType(type);
660                        WORD wSeverity = EventLogRecord::translateSeverity(severity);
661                        WORD dwCategory = EventLogRecord::translateType(category);
662                        DWORD tID = (wEventID&0xffff) | (wSeverity<<30);
663
664                        int size = 0;
665                        BOOST_FOREACH(const std::wstring &s, strings) {
666                                size += s.size()+1;
667                        }
668                        LPCWSTR *string_data = new LPCWSTR[strings.size()];
669                        int i=0;
670                        BOOST_FOREACH(const std::wstring &s, strings) {
671                                string_data[i++] = s.c_str();
672                        }
673
674                        if (!ReportEvent(source, dwType, dwCategory, tID, NULL, strings.size(), 0, string_data, NULL)) {
675                                message = _T("Could not report the event");
676                                return NSCAPI::hasFailed;
677                        } else {
678                                message = _T("Message reported successfully");
679                        }
680                        delete [] string_data;
681                }
682        } catch (const std::exception &e) {
683                NSC_LOG_ERROR_STD(_T("Failed to parse command line: ") + utf8::cvt<std::wstring>(e.what()));
684        }
685
686
687        return NSCAPI::returnIgnored;
688}
689
690NSC_WRAP_DLL();
691NSC_WRAPPERS_MAIN_DEF(CheckEventLog);
692NSC_WRAPPERS_IGNORE_MSG_DEF();
693NSC_WRAPPERS_HANDLE_CMD_DEF();
694NSC_WRAPPERS_CLI_DEF();
Note: See TracBrowser for help on using the repository browser.