]> granicus.if.org Git - icinga2/blob - plugins/check_network.cpp
Update documentation for 2.2.1
[icinga2] / plugins / check_network.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
4  *                                                                            *
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.                     *
9  *                                                                            *
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.                               *
14  *                                                                            *
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  ******************************************************************************/
19 #include <Windows.h>
20 #include <Pdh.h>
21 #include <Shlwapi.h>
22 #include <iostream>
23 #include <pdhmsg.h>
24
25 #include "thresholds.h"
26
27 #include "boost/program_options.hpp"
28
29 #define VERSION 1.0
30 namespace po = boost::program_options;
31
32 using std::endl; using std::vector; using std::wstring;
33 using std::wcout; using std::cout;
34 struct nInterface 
35 {
36         wstring name;
37         long BytesInSec, BytesOutSec;
38         nInterface(wstring p)
39                 : name(p)
40         {}
41 };
42
43 struct printInfoStruct 
44 {
45         threshold warn, crit;
46 };
47
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>&);
51
52 int wmain(int argc, wchar_t **argv) 
53 {
54         vector<nInterface> vInterfaces;
55         printInfoStruct printInfo{ };
56         po::variables_map vm;
57         int ret = parseArguments(argc, argv, vm, printInfo);
58         if (ret != -1)
59                 return ret;
60
61         ret = check_network(vInterfaces);
62         if (ret != -1)
63                 return ret;
64                 
65         printOutput(printInfo, vInterfaces);
66         return 1;
67 }
68
69 int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo) 
70 {
71         wchar_t namePath[MAX_PATH];
72         GetModuleFileName(NULL, namePath, MAX_PATH);
73         wchar_t *progName = PathFindFileName(namePath);
74
75         po::options_description desc("Options");
76
77         desc.add_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")
83                 ;
84
85         po::basic_command_line_parser<wchar_t> parser(ac, av);
86
87         try {
88                 po::store(
89                         parser
90                         .options(desc)
91                         .style(
92                         po::command_line_style::unix_style |
93                         po::command_line_style::allow_long_disguise)
94                         .run(),
95                         vm);
96                 vm.notify();
97         } catch (std::exception& e) {
98                 cout << e.what() << endl << desc << endl;
99                 return 3;
100         }
101
102         if (vm.count("h")) {
103                 cout << desc << endl;
104                 return 0;
105         }
106
107         if (vm.count("help")) {
108                 wcout << progName << " Help\n\tVersion: " << VERSION << endl;
109                 wprintf(
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);
112                 cout << desc;
113                 wprintf(
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"
123                         L"by interface\n\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"
130                         L"-w THRESHOLD\n"
131                         L"warn if threshold is broken, which means VALUE > THRESHOLD\n"
132                         L"(unless stated differently)\n\n"
133                         L"-w !THRESHOLD\n"
134                         L"inverts threshold check, VALUE < THRESHOLD (analogous to above)\n\n"
135                         L"-w [THR1-THR2]\n"
136                         L"warn is VALUE is inside the range spanned by THR1 and THR2\n\n"
137                         L"-w ![THR1-THR2]\n"
138                         L"warn if VALUE is outside the range spanned by THR1 and THR2\n\n"
139                         L"-w THRESHOLD%%\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."
145                         , progName);
146                 cout << endl;
147                 return 0;
148         }
149
150         if (vm.count("version"))
151                 cout << "Version: " << VERSION << endl;
152
153         if (vm.count("warning")) {
154                 try {
155                         printInfo.warn = threshold(vm["warning"].as<wstring>());
156                 } catch (std::invalid_argument& e) {
157                         cout << e.what() << endl;
158                         return 3;
159                 }
160         }
161         if (vm.count("critical")) {
162                 try {
163                         printInfo.crit = threshold(vm["critical"].as<wstring>());
164                 } catch (std::invalid_argument& e) {
165                         cout << e.what() << endl;
166                         return 3;
167                 }
168         }
169         
170         return -1;
171 }
172
173 int printOutput(printInfoStruct& printInfo, const vector<nInterface>& vInterfaces) 
174 {
175         long tIn = 0, tOut = 0;
176         std::wstringstream tss, perfDataFirst;
177         state state = OK;
178
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 ";
183         }
184
185         if (printInfo.warn.rend(tIn + tOut))
186                 state = WARNING;
187         if (printInfo.crit.rend(tIn + tOut))
188                 state = CRITICAL;
189         
190         perfDataFirst << L"network=" << tIn + tOut << L"B/s;" << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";" << L"0 ";
191
192         switch (state) {
193         case OK:
194                 wcout << L"NETWORK OK " << tIn + tOut << L"B/s|" << perfDataFirst.str() << tss.str() << endl;
195                 break;
196         case WARNING:
197                 wcout << L"NETWORK WARNING " << tIn + tOut << L"B/s|" << perfDataFirst.str() << tss.str() << endl;
198                 break;
199         case CRITICAL:
200                 wcout << L"NETWORK CRITICAL " << tIn + tOut << L"B/s|" << perfDataFirst.str() << tss.str() << endl;
201                 break;
202         }
203
204         return state;
205 }
206
207 int check_network(vector <nInterface>& vInterfaces) 
208 {
209         const wchar_t *perfIn = L"\\Network Interface(*)\\Bytes Received/sec";
210         const wchar_t *perfOut = L"\\Network Interface(*)\\Bytes Sent/sec";
211
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;
216         PDH_STATUS err;
217
218         err = PdhOpenQuery(NULL, NULL, &phQuery);
219         if (!SUCCEEDED(err))
220                 goto die;
221
222         err = PdhAddEnglishCounter(phQuery, perfIn, NULL, &phCounterIn);
223         if (!SUCCEEDED(err)) 
224                 goto die;
225         
226         err = PdhAddEnglishCounter(phQuery, perfOut, NULL, &phCounterOut);
227         if (!SUCCEEDED(err)) 
228                 goto die;
229         
230         err = PdhCollectQueryData(phQuery);
231         if (!SUCCEEDED(err))
232                 goto die;
233         
234         Sleep(1000);
235
236         err = PdhCollectQueryData(phQuery);
237         if (!SUCCEEDED(err))
238                 goto die;
239
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]);
243         else
244                 goto die;
245         
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]);
249         else
250                 goto die;
251
252         err = PdhGetFormattedCounterArray(phCounterIn, PDH_FMT_LONG, &dwBufferSizeIn, &dwItemCount, pDisplayValuesIn);
253         if (!SUCCEEDED(err))
254                 goto die;
255
256         err = PdhGetFormattedCounterArray(phCounterOut, PDH_FMT_LONG, &dwBufferSizeOut, &dwItemCount, pDisplayValuesOut);
257         if (!SUCCEEDED(err))
258                 goto die;
259
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);
265         }
266                 PdhCloseQuery(phQuery);
267                 delete pDisplayValuesIn;
268                 delete pDisplayValuesOut;
269                 return -1;
270 die:
271         die(err);
272         if (phQuery)
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);
278         return 3;
279 }