1 /******************************************************************************
3 * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
25 #include "thresholds.h"
27 #include "boost/program_options.hpp"
30 namespace po = boost::program_options;
32 using std::endl; using std::vector; using std::wstring;
33 using std::wcout; using std::cout;
37 long BytesInSec, BytesOutSec;
43 struct printInfoStruct
48 static int parseArguments(int, TCHAR **, po::variables_map&, printInfoStruct&);
49 static int printOutput(printInfoStruct&, const vector<nInterface>&);
50 static int check_network(vector<nInterface>&);
52 int wmain(int argc, wchar_t **argv)
54 vector<nInterface> vInterfaces;
55 printInfoStruct printInfo{ };
57 int ret = parseArguments(argc, argv, vm, printInfo);
61 ret = check_network(vInterfaces);
65 printOutput(printInfo, vInterfaces);
69 int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo)
71 wchar_t namePath[MAX_PATH];
72 GetModuleFileName(NULL, namePath, MAX_PATH);
73 wchar_t *progName = PathFindFileName(namePath);
75 po::options_description desc("Options");
78 (",h", "print usage and exit")
79 ("help", "print help message and exit")
80 ("version,v", "print version and exit")
81 ("warning,w", po::wvalue<wstring>(), "warning value")
82 ("critical,c", po::wvalue<wstring>(), "critical value")
85 po::basic_command_line_parser<wchar_t> parser(ac, av);
92 po::command_line_style::unix_style |
93 po::command_line_style::allow_long_disguise)
97 } catch (std::exception& e) {
98 cout << e.what() << endl << desc << endl;
103 cout << desc << endl;
107 if (vm.count("help")) {
108 wcout << progName << " Help\n\tVersion: " << VERSION << endl;
110 L"%s is a simple program to check a machines network performance.\n"
111 L"You can use the following options to define its behaviour:\n\n", progName);
114 L"\nIt will then output a string looking something like this:\n\n"
115 L"\tNETWORK WARNING 1131B/s|network=1131B/s;1000;7000;0\n\n"
116 L"\"DISK\" being the type of the check, \"WARNING\" the returned status\n"
117 L"and \"1131B/s\" is the returned value.\n"
118 L"The performance data is found behind the \"|\", in order:\n"
119 L"returned value, warning threshold, critical threshold, minimal value and,\n"
120 L"if applicable, the maximal value. Performance data will only be displayed when\n"
121 L"you set at least one threshold\n\n"
122 L"This program will also print out additional performance data interface\n"
124 L"%s' exit codes denote the following:\n"
125 L" 0\tOK,\n\tNo Thresholds were broken or the programs check part was not executed\n"
126 L" 1\tWARNING,\n\tThe warning, but not the critical threshold was broken\n"
127 L" 2\tCRITICAL,\n\tThe critical threshold was broken\n"
128 L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
129 L"Threshold syntax:\n\n"
131 L"warn if threshold is broken, which means VALUE > THRESHOLD\n"
132 L"(unless stated differently)\n\n"
134 L"inverts threshold check, VALUE < THRESHOLD (analogous to above)\n\n"
136 L"warn is VALUE is inside the range spanned by THR1 and THR2\n\n"
138 L"warn if VALUE is outside the range spanned by THR1 and THR2\n\n"
140 L"if the plugin accepts percentage based thresholds those will be used.\n"
141 L"Does nothing if the plugin does not accept percentages, or only uses\n"
142 L"percentage thresholds. Ranges can be used with \"%%\", but both range values need\n"
143 L"to end with a percentage sign.\n\n"
144 L"All of these options work with the critical threshold \"-c\" too."
150 if (vm.count("version"))
151 cout << "Version: " << VERSION << endl;
153 if (vm.count("warning")) {
155 printInfo.warn = threshold(vm["warning"].as<wstring>());
156 } catch (std::invalid_argument& e) {
157 cout << e.what() << endl;
161 if (vm.count("critical")) {
163 printInfo.crit = threshold(vm["critical"].as<wstring>());
164 } catch (std::invalid_argument& e) {
165 cout << e.what() << endl;
173 int printOutput(printInfoStruct& printInfo, const vector<nInterface>& vInterfaces)
175 long tIn = 0, tOut = 0;
176 std::wstringstream tss, perfDataFirst;
179 for (vector<nInterface>::const_iterator it = vInterfaces.begin(); it != vInterfaces.end(); ++it) {
180 tIn += it->BytesInSec;
181 tOut += it->BytesOutSec;
182 tss << L"netI=\"" << it->name << L"\";in=" << it->BytesInSec << L"B/s;out=" << it->BytesOutSec << L"B/s ";
185 if (printInfo.warn.rend(tIn + tOut))
187 if (printInfo.crit.rend(tIn + tOut))
190 perfDataFirst << L"network=" << tIn + tOut << L"B/s;" << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";" << L"0 ";
194 wcout << L"NETWORK OK " << tIn + tOut << L"B/s|" << perfDataFirst.str() << tss.str() << endl;
197 wcout << L"NETWORK WARNING " << tIn + tOut << L"B/s|" << perfDataFirst.str() << tss.str() << endl;
200 wcout << L"NETWORK CRITICAL " << tIn + tOut << L"B/s|" << perfDataFirst.str() << tss.str() << endl;
207 int check_network(vector <nInterface>& vInterfaces)
209 const wchar_t *perfIn = L"\\Network Interface(*)\\Bytes Received/sec";
210 const wchar_t *perfOut = L"\\Network Interface(*)\\Bytes Sent/sec";
212 PDH_HQUERY phQuery = NULL;
213 PDH_HCOUNTER phCounterIn, phCounterOut;
214 DWORD dwBufferSizeIn = 0, dwBufferSizeOut = 0, dwItemCount = 0;
215 PDH_FMT_COUNTERVALUE_ITEM *pDisplayValuesIn = NULL, *pDisplayValuesOut = NULL;
218 err = PdhOpenQuery(NULL, NULL, &phQuery);
222 err = PdhAddEnglishCounter(phQuery, perfIn, NULL, &phCounterIn);
226 err = PdhAddEnglishCounter(phQuery, perfOut, NULL, &phCounterOut);
230 err = PdhCollectQueryData(phQuery);
236 err = PdhCollectQueryData(phQuery);
240 err = PdhGetFormattedCounterArray(phCounterIn, PDH_FMT_LONG, &dwBufferSizeIn, &dwItemCount, pDisplayValuesIn);
241 if (err == PDH_MORE_DATA || SUCCEEDED(err))
242 pDisplayValuesIn = reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(new BYTE[dwItemCount*dwBufferSizeIn]);
246 err = PdhGetFormattedCounterArray(phCounterOut, PDH_FMT_LONG, &dwBufferSizeOut, &dwItemCount, pDisplayValuesOut);
247 if (err == PDH_MORE_DATA || SUCCEEDED(err))
248 pDisplayValuesOut = reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(new BYTE[dwItemCount*dwBufferSizeIn]);
252 err = PdhGetFormattedCounterArray(phCounterIn, PDH_FMT_LONG, &dwBufferSizeIn, &dwItemCount, pDisplayValuesIn);
256 err = PdhGetFormattedCounterArray(phCounterOut, PDH_FMT_LONG, &dwBufferSizeOut, &dwItemCount, pDisplayValuesOut);
260 for (DWORD i = 0; i < dwItemCount; i++) {
261 nInterface *iface = new nInterface(wstring(pDisplayValuesIn[i].szName));
262 iface->BytesInSec = pDisplayValuesIn[i].FmtValue.longValue;
263 iface->BytesOutSec = pDisplayValuesOut[i].FmtValue.longValue;
264 vInterfaces.push_back(*iface);
266 PdhCloseQuery(phQuery);
267 delete pDisplayValuesIn;
268 delete pDisplayValuesOut;
273 PdhCloseQuery(phQuery);
274 if (pDisplayValuesIn)
275 delete reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(pDisplayValuesIn);
276 if (pDisplayValuesOut)
277 delete reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(pDisplayValuesOut);