check_snmp.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. /*****************************************************************************
  2. *
  3. * Nagios check_snmp plugin
  4. *
  5. * License: GPL
  6. * Copyright (c) 1999-2007 Nagios Plugins Development Team
  7. *
  8. * Description:
  9. *
  10. * This file contains the check_snmp plugin
  11. *
  12. * Check status of remote machines and obtain system information via SNMP
  13. *
  14. *
  15. * This program is free software: you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation, either version 3 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  27. *
  28. *
  29. *****************************************************************************/
  30. const char *progname = "check_snmp";
  31. const char *copyright = "1999-2007";
  32. const char *email = "nagiosplug-devel@lists.sourceforge.net";
  33. #include "common.h"
  34. #include "utils.h"
  35. #include "utils_cmd.h"
  36. #define DEFAULT_COMMUNITY "public"
  37. #define DEFAULT_PORT "161"
  38. #define DEFAULT_MIBLIST "ALL"
  39. #define DEFAULT_PROTOCOL "1"
  40. #define DEFAULT_TIMEOUT 1
  41. #define DEFAULT_RETRIES 5
  42. #define DEFAULT_AUTH_PROTOCOL "MD5"
  43. #define DEFAULT_PRIV_PROTOCOL "DES"
  44. #define DEFAULT_DELIMITER "="
  45. #define DEFAULT_OUTPUT_DELIMITER " "
  46. #define mark(a) ((a)!=0?"*":"")
  47. #define CHECK_UNDEF 0
  48. #define CRIT_PRESENT 1
  49. #define CRIT_STRING 2
  50. #define CRIT_REGEX 4
  51. #define WARN_PRESENT 8
  52. #define WARN_STRING 16
  53. #define WARN_REGEX 32
  54. #define MAX_OIDS 8
  55. int process_arguments (int, char **);
  56. int validate_arguments (void);
  57. char *thisarg (char *str);
  58. char *nextarg (char *str);
  59. void print_usage (void);
  60. void print_help (void);
  61. #include "regex.h"
  62. char regex_expect[MAX_INPUT_BUFFER] = "";
  63. regex_t preg;
  64. regmatch_t pmatch[10];
  65. char errbuf[MAX_INPUT_BUFFER] = "";
  66. char perfstr[MAX_INPUT_BUFFER] = "| ";
  67. int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
  68. int eflags = 0;
  69. int errcode, excode;
  70. char *server_address = NULL;
  71. char *community = NULL;
  72. char **authpriv = NULL;
  73. char *proto = NULL;
  74. char *seclevel = NULL;
  75. char *secname = NULL;
  76. char *authproto = NULL;
  77. char *privproto = NULL;
  78. char *authpasswd = NULL;
  79. char *privpasswd = NULL;
  80. char **oids = NULL;
  81. char *label;
  82. char *units;
  83. char *port;
  84. char *snmpcmd;
  85. char string_value[MAX_INPUT_BUFFER] = "";
  86. char **labels = NULL;
  87. char **unitv = NULL;
  88. size_t nlabels = 0;
  89. size_t labels_size = 8;
  90. size_t nunits = 0;
  91. size_t unitv_size = 8;
  92. int numoids = 0;
  93. int numauthpriv = 0;
  94. int verbose = 0;
  95. int usesnmpgetnext = FALSE;
  96. char *warning_thresholds = NULL;
  97. char *critical_thresholds = NULL;
  98. thresholds *thlds[MAX_OIDS];
  99. double response_value[MAX_OIDS];
  100. int retries = 0;
  101. int eval_method[MAX_OIDS];
  102. char *delimiter;
  103. char *output_delim;
  104. char *miblist = NULL;
  105. int needmibs = FALSE;
  106. int
  107. main (int argc, char **argv)
  108. {
  109. int i;
  110. int iresult = STATE_UNKNOWN;
  111. int result = STATE_UNKNOWN;
  112. int return_code = 0;
  113. int external_error = 0;
  114. char **command_line = NULL;
  115. char *cl_hidden_auth = NULL;
  116. char *oidname = NULL;
  117. char *response = NULL;
  118. char *outbuff;
  119. char *ptr = NULL;
  120. char *show = NULL;
  121. char *th_warn=NULL;
  122. char *th_crit=NULL;
  123. char type[8] = "";
  124. output chld_out, chld_err;
  125. setlocale (LC_ALL, "");
  126. bindtextdomain (PACKAGE, LOCALEDIR);
  127. textdomain (PACKAGE);
  128. labels = malloc (labels_size);
  129. unitv = malloc (unitv_size);
  130. for (i = 0; i < MAX_OIDS; i++)
  131. eval_method[i] = CHECK_UNDEF;
  132. label = strdup ("SNMP");
  133. units = strdup ("");
  134. port = strdup (DEFAULT_PORT);
  135. outbuff = strdup ("");
  136. delimiter = strdup (" = ");
  137. output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
  138. timeout_interval = DEFAULT_TIMEOUT;
  139. retries = DEFAULT_RETRIES;
  140. /* Parse extra opts if any */
  141. argv=np_extra_opts (&argc, argv, progname);
  142. if (process_arguments (argc, argv) == ERROR)
  143. usage4 (_("Could not parse arguments"));
  144. /* Populate the thresholds */
  145. th_warn=warning_thresholds;
  146. th_crit=critical_thresholds;
  147. for (i=0; i<numoids; i++) {
  148. char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
  149. char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
  150. /* Skip empty thresholds, while avoiding segfault */
  151. set_thresholds(&thlds[i],
  152. w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
  153. c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
  154. if (w) {
  155. th_warn=strchr(th_warn, ',');
  156. if (th_warn) th_warn++;
  157. free(w);
  158. }
  159. if (c) {
  160. th_crit=strchr(th_crit, ',');
  161. if (th_crit) th_crit++;
  162. free(c);
  163. }
  164. }
  165. /* Create the command array to execute */
  166. if(usesnmpgetnext == TRUE) {
  167. snmpcmd = strdup (PATH_TO_SNMPGETNEXT);
  168. }else{
  169. snmpcmd = strdup (PATH_TO_SNMPGET);
  170. }
  171. /* 9 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */
  172. command_line = calloc (9 + numauthpriv + 1 + numoids + 1, sizeof (char *));
  173. command_line[0] = snmpcmd;
  174. command_line[1] = strdup ("-t");
  175. asprintf (&command_line[2], "%d", timeout_interval);
  176. command_line[3] = strdup ("-r");
  177. asprintf (&command_line[4], "%d", retries);
  178. command_line[5] = strdup ("-m");
  179. command_line[6] = strdup (miblist);
  180. command_line[7] = "-v";
  181. command_line[8] = strdup (proto);
  182. for (i = 0; i < numauthpriv; i++) {
  183. command_line[9 + i] = authpriv[i];
  184. }
  185. asprintf (&command_line[9 + numauthpriv], "%s:%s", server_address, port);
  186. /* This is just for display purposes, so it can remain a string */
  187. asprintf(&cl_hidden_auth, "%s -t %d -r %d -m %s -v %s %s %s:%s",
  188. snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto, "[authpriv]",
  189. server_address, port);
  190. for (i = 0; i < numoids; i++) {
  191. command_line[9 + numauthpriv + 1 + i] = oids[i];
  192. asprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);
  193. }
  194. command_line[9 + numauthpriv + 1 + numoids] = NULL;
  195. if (verbose)
  196. printf ("%s\n", cl_hidden_auth);
  197. /* Run the command */
  198. return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0);
  199. /* Due to net-snmp sometimes showing stderr messages with poorly formed MIBs,
  200. only return state unknown if return code is non zero or there is no stdout.
  201. Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
  202. */
  203. if (return_code != 0)
  204. external_error=1;
  205. if (chld_out.lines == 0)
  206. external_error=1;
  207. if (external_error) {
  208. if (chld_err.lines > 0) {
  209. printf (_("External command error: %s\n"), chld_err.line[0]);
  210. for (i = 1; i < chld_err.lines; i++) {
  211. printf ("%s\n", chld_err.line[i]);
  212. }
  213. } else {
  214. printf(_("External command error with no output (return code: %d)\n"), return_code);
  215. }
  216. exit (STATE_UNKNOWN);
  217. }
  218. if (verbose) {
  219. for (i = 0; i < chld_out.lines; i++) {
  220. printf ("%s\n", chld_out.line[i]);
  221. }
  222. }
  223. for (i = 0; i < chld_out.lines; i++) {
  224. const char *conv = "%.0f";
  225. ptr = chld_out.line[i];
  226. oidname = strpcpy (oidname, ptr, delimiter);
  227. response = strstr (ptr, delimiter);
  228. if (response == NULL)
  229. break;
  230. if (verbose > 2) {
  231. printf("Processing line %i\n oidname: %s\n response: %s\n", i+1, oidname, response);
  232. }
  233. /* Clean up type array - Sol10 does not necessarily zero it out */
  234. bzero(type, sizeof(type));
  235. /* We strip out the datatype indicator for PHBs */
  236. if (strstr (response, "Gauge: "))
  237. show = strstr (response, "Gauge: ") + 7;
  238. else if (strstr (response, "Gauge32: "))
  239. show = strstr (response, "Gauge32: ") + 9;
  240. else if (strstr (response, "Counter32: ")) {
  241. show = strstr (response, "Counter32: ") + 11;
  242. strcpy(type, "c");
  243. }
  244. else if (strstr (response, "Counter64: ")) {
  245. show = strstr (response, "Counter64: ") + 11;
  246. strcpy(type, "c");
  247. }
  248. else if (strstr (response, "INTEGER: "))
  249. show = strstr (response, "INTEGER: ") + 9;
  250. else if (strstr (response, "STRING: ")) {
  251. show = strstr (response, "STRING: ") + 8;
  252. conv = "%.10g";
  253. }
  254. else if (strstr (response, "Timeticks: "))
  255. show = strstr (response, "Timeticks: ");
  256. else
  257. show = response;
  258. iresult = STATE_DEPENDENT;
  259. /* Process this block for integer comparisons */
  260. if (thlds[i]->warning || thlds[i]->critical) {
  261. ptr = strpbrk (show, "0123456789");
  262. if (ptr == NULL)
  263. die (STATE_UNKNOWN,_("No valid data returned"));
  264. response_value[i] = strtod (ptr, NULL);
  265. iresult = get_status(response_value[i], thlds[i]);
  266. asprintf (&show, conv, response_value[i]);
  267. }
  268. /* Process this block for string matching */
  269. else if (eval_method[i] & CRIT_STRING) {
  270. if (strcmp (show, string_value))
  271. iresult = STATE_CRITICAL;
  272. else
  273. iresult = STATE_OK;
  274. }
  275. /* Process this block for regex matching */
  276. else if (eval_method[i] & CRIT_REGEX) {
  277. excode = regexec (&preg, response, 10, pmatch, eflags);
  278. if (excode == 0) {
  279. iresult = STATE_OK;
  280. }
  281. else if (excode != REG_NOMATCH) {
  282. regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
  283. printf (_("Execute Error: %s\n"), errbuf);
  284. exit (STATE_CRITICAL);
  285. }
  286. else {
  287. iresult = STATE_CRITICAL;
  288. }
  289. }
  290. /* Process this block for existence-nonexistence checks */
  291. else {
  292. if (eval_method[i] & CRIT_PRESENT)
  293. iresult = STATE_CRITICAL;
  294. else if (eval_method[i] & WARN_PRESENT)
  295. iresult = STATE_WARNING;
  296. else if (response && iresult == STATE_DEPENDENT)
  297. iresult = STATE_OK;
  298. }
  299. /* Result is the worst outcome of all the OIDs tested */
  300. result = max_state (result, iresult);
  301. /* Prepend a label for this OID if there is one */
  302. if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
  303. asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
  304. (i == 0) ? " " : output_delim,
  305. labels[i], mark (iresult), show, mark (iresult));
  306. else
  307. asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
  308. mark (iresult), show, mark (iresult));
  309. /* Append a unit string for this OID if there is one */
  310. if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
  311. asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
  312. if (is_numeric(show)) {
  313. strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
  314. strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
  315. strncat(perfstr, show, sizeof(perfstr)-strlen(perfstr)-1);
  316. if (type)
  317. strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
  318. strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
  319. }
  320. }
  321. printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
  322. return result;
  323. }
  324. /* process command-line arguments */
  325. int
  326. process_arguments (int argc, char **argv)
  327. {
  328. char *ptr;
  329. int c = 1;
  330. int j = 0, jj = 0, ii = 0;
  331. int option = 0;
  332. static struct option longopts[] = {
  333. STD_LONG_OPTS,
  334. {"community", required_argument, 0, 'C'},
  335. {"oid", required_argument, 0, 'o'},
  336. {"object", required_argument, 0, 'o'},
  337. {"delimiter", required_argument, 0, 'd'},
  338. {"output-delimiter", required_argument, 0, 'D'},
  339. {"string", required_argument, 0, 's'},
  340. {"timeout", required_argument, 0, 't'},
  341. {"regex", required_argument, 0, 'r'},
  342. {"ereg", required_argument, 0, 'r'},
  343. {"eregi", required_argument, 0, 'R'},
  344. {"label", required_argument, 0, 'l'},
  345. {"units", required_argument, 0, 'u'},
  346. {"port", required_argument, 0, 'p'},
  347. {"retries", required_argument, 0, 'e'},
  348. {"miblist", required_argument, 0, 'm'},
  349. {"protocol", required_argument, 0, 'P'},
  350. {"seclevel", required_argument, 0, 'L'},
  351. {"secname", required_argument, 0, 'U'},
  352. {"authproto", required_argument, 0, 'a'},
  353. {"privproto", required_argument, 0, 'x'},
  354. {"authpasswd", required_argument, 0, 'A'},
  355. {"privpasswd", required_argument, 0, 'X'},
  356. {"next", no_argument, 0, 'n'},
  357. {0, 0, 0, 0}
  358. };
  359. if (argc < 2)
  360. return ERROR;
  361. /* reverse compatibility for very old non-POSIX usage forms */
  362. for (c = 1; c < argc; c++) {
  363. if (strcmp ("-to", argv[c]) == 0)
  364. strcpy (argv[c], "-t");
  365. if (strcmp ("-wv", argv[c]) == 0)
  366. strcpy (argv[c], "-w");
  367. if (strcmp ("-cv", argv[c]) == 0)
  368. strcpy (argv[c], "-c");
  369. }
  370. while (1) {
  371. c = getopt_long (argc, argv, "nhvVt:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:L:U:a:x:A:X:",
  372. longopts, &option);
  373. if (c == -1 || c == EOF)
  374. break;
  375. switch (c) {
  376. case '?': /* usage */
  377. usage5 ();
  378. case 'h': /* help */
  379. print_help ();
  380. exit (STATE_OK);
  381. case 'V': /* version */
  382. print_revision (progname, NP_VERSION);
  383. exit (STATE_OK);
  384. case 'v': /* verbose */
  385. verbose++;
  386. break;
  387. /* Connection info */
  388. case 'C': /* group or community */
  389. community = optarg;
  390. break;
  391. case 'H': /* Host or server */
  392. server_address = optarg;
  393. break;
  394. case 'p': /* TCP port number */
  395. port = optarg;
  396. break;
  397. case 'm': /* List of MIBS */
  398. miblist = optarg;
  399. break;
  400. case 'n': /* usesnmpgetnext */
  401. usesnmpgetnext = TRUE;
  402. break;
  403. case 'P': /* SNMP protocol version */
  404. proto = optarg;
  405. break;
  406. case 'L': /* security level */
  407. seclevel = optarg;
  408. break;
  409. case 'U': /* security username */
  410. secname = optarg;
  411. break;
  412. case 'a': /* auth protocol */
  413. authproto = optarg;
  414. break;
  415. case 'x': /* priv protocol */
  416. privproto = optarg;
  417. break;
  418. case 'A': /* auth passwd */
  419. authpasswd = optarg;
  420. break;
  421. case 'X': /* priv passwd */
  422. privpasswd = optarg;
  423. break;
  424. case 't': /* timeout period */
  425. if (!is_integer (optarg))
  426. usage2 (_("Timeout interval must be a positive integer"), optarg);
  427. else
  428. timeout_interval = atoi (optarg);
  429. break;
  430. /* Test parameters */
  431. case 'c': /* critical threshold */
  432. critical_thresholds = optarg;
  433. break;
  434. case 'w': /* warning threshold */
  435. warning_thresholds = optarg;
  436. break;
  437. case 'e': /* PRELIMINARY - may change */
  438. case 'E': /* PRELIMINARY - may change */
  439. if (!is_integer (optarg))
  440. usage2 (_("Retries interval must be a positive integer"), optarg);
  441. else
  442. retries = atoi(optarg);
  443. break;
  444. case 'o': /* object identifier */
  445. if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
  446. /*
  447. * we have something other than digits, periods and comas,
  448. * so we have a mib variable, rather than just an SNMP OID,
  449. * so we have to actually read the mib files
  450. */
  451. needmibs = TRUE;
  452. }
  453. if (!oids) oids = calloc(MAX_OIDS, sizeof (char *));
  454. for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
  455. oids[j] = strdup(ptr);
  456. }
  457. numoids = j;
  458. if (c == 'E' || c == 'e') {
  459. jj++;
  460. ii++;
  461. }
  462. if (c == 'E')
  463. eval_method[j+1] |= WARN_PRESENT;
  464. else if (c == 'e')
  465. eval_method[j+1] |= CRIT_PRESENT;
  466. break;
  467. case 's': /* string or substring */
  468. strncpy (string_value, optarg, sizeof (string_value) - 1);
  469. string_value[sizeof (string_value) - 1] = 0;
  470. eval_method[jj++] = CRIT_STRING;
  471. ii++;
  472. break;
  473. case 'R': /* regex */
  474. cflags = REG_ICASE;
  475. case 'r': /* regex */
  476. cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
  477. strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
  478. regex_expect[sizeof (regex_expect) - 1] = 0;
  479. errcode = regcomp (&preg, regex_expect, cflags);
  480. if (errcode != 0) {
  481. regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
  482. printf (_("Could Not Compile Regular Expression"));
  483. return ERROR;
  484. }
  485. eval_method[jj++] = CRIT_REGEX;
  486. ii++;
  487. break;
  488. /* Format */
  489. case 'd': /* delimiter */
  490. delimiter = strscpy (delimiter, optarg);
  491. break;
  492. case 'D': /* output-delimiter */
  493. output_delim = strscpy (output_delim, optarg);
  494. break;
  495. case 'l': /* label */
  496. label = optarg;
  497. nlabels++;
  498. if (nlabels >= labels_size) {
  499. labels_size += 8;
  500. labels = realloc (labels, labels_size);
  501. if (labels == NULL)
  502. die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
  503. }
  504. labels[nlabels - 1] = optarg;
  505. ptr = thisarg (optarg);
  506. labels[nlabels - 1] = ptr;
  507. if (strstr (ptr, "'") == ptr)
  508. labels[nlabels - 1] = ptr + 1;
  509. while (ptr && (ptr = nextarg (ptr))) {
  510. if (nlabels >= labels_size) {
  511. labels_size += 8;
  512. labels = realloc (labels, labels_size);
  513. if (labels == NULL)
  514. die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
  515. }
  516. labels++;
  517. ptr = thisarg (ptr);
  518. if (strstr (ptr, "'") == ptr)
  519. labels[nlabels - 1] = ptr + 1;
  520. else
  521. labels[nlabels - 1] = ptr;
  522. }
  523. break;
  524. case 'u': /* units */
  525. units = optarg;
  526. nunits++;
  527. if (nunits >= unitv_size) {
  528. unitv_size += 8;
  529. unitv = realloc (unitv, unitv_size);
  530. if (unitv == NULL)
  531. die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
  532. }
  533. unitv[nunits - 1] = optarg;
  534. ptr = thisarg (optarg);
  535. unitv[nunits - 1] = ptr;
  536. if (strstr (ptr, "'") == ptr)
  537. unitv[nunits - 1] = ptr + 1;
  538. while (ptr && (ptr = nextarg (ptr))) {
  539. if (nunits >= unitv_size) {
  540. unitv_size += 8;
  541. unitv = realloc (unitv, unitv_size);
  542. if (units == NULL)
  543. die (STATE_UNKNOWN, _("Could not realloc() units\n"));
  544. }
  545. nunits++;
  546. ptr = thisarg (ptr);
  547. if (strstr (ptr, "'") == ptr)
  548. unitv[nunits - 1] = ptr + 1;
  549. else
  550. unitv[nunits - 1] = ptr;
  551. }
  552. break;
  553. }
  554. }
  555. if (server_address == NULL)
  556. server_address = argv[optind];
  557. if (community == NULL)
  558. community = strdup (DEFAULT_COMMUNITY);
  559. return validate_arguments ();
  560. }
  561. /******************************************************************************
  562. @@-
  563. <sect3>
  564. <title>validate_arguments</title>
  565. <para>&PROTO_validate_arguments;</para>
  566. <para>Checks to see if the default miblist needs to be loaded. Also verifies
  567. the authentication and authorization combinations based on protocol version
  568. selected.</para>
  569. <para></para>
  570. </sect3>
  571. -@@
  572. ******************************************************************************/
  573. int
  574. validate_arguments ()
  575. {
  576. /* check whether to load locally installed MIBS (CPU/disk intensive) */
  577. if (miblist == NULL) {
  578. if ( needmibs == TRUE ) {
  579. miblist = strdup (DEFAULT_MIBLIST);
  580. }else{
  581. miblist = ""; /* don't read any mib files for numeric oids */
  582. }
  583. }
  584. /* Check server_address is given */
  585. if (server_address == NULL)
  586. die(STATE_UNKNOWN, _("No host specified\n"));
  587. /* Check oid is given */
  588. if (numoids == 0)
  589. die(STATE_UNKNOWN, _("No OIDs specified\n"));
  590. if (proto == NULL)
  591. asprintf(&proto, DEFAULT_PROTOCOL);
  592. if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */
  593. numauthpriv = 2;
  594. authpriv = calloc (numauthpriv, sizeof (char *));
  595. authpriv[0] = strdup ("-c");
  596. authpriv[1] = strdup (community);
  597. }
  598. else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
  599. if (seclevel == NULL)
  600. asprintf(&seclevel, "noAuthNoPriv");
  601. if (strcmp(seclevel, "noAuthNoPriv") == 0) {
  602. numauthpriv = 2;
  603. authpriv = calloc (numauthpriv, sizeof (char *));
  604. authpriv[0] = strdup ("-l");
  605. authpriv[1] = strdup ("noAuthNoPriv");
  606. } else {
  607. if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
  608. usage2 (_("Invalid seclevel"), seclevel);
  609. }
  610. if (authproto == NULL )
  611. asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
  612. if (secname == NULL)
  613. die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
  614. if (authpasswd == NULL)
  615. die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
  616. if ( strcmp(seclevel, "authNoPriv") == 0 ) {
  617. numauthpriv = 8;
  618. authpriv = calloc (numauthpriv, sizeof (char *));
  619. authpriv[0] = strdup ("-l");
  620. authpriv[1] = strdup ("authNoPriv");
  621. authpriv[2] = strdup ("-a");
  622. authpriv[3] = strdup (authproto);
  623. authpriv[4] = strdup ("-u");
  624. authpriv[5] = strdup (secname);
  625. authpriv[6] = strdup ("-A");
  626. authpriv[7] = strdup (authpasswd);
  627. } else if ( strcmp(seclevel, "authPriv") == 0 ) {
  628. if (privproto == NULL )
  629. asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
  630. if (privpasswd == NULL)
  631. die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
  632. numauthpriv = 12;
  633. authpriv = calloc (numauthpriv, sizeof (char *));
  634. authpriv[0] = strdup ("-l");
  635. authpriv[1] = strdup ("authPriv");
  636. authpriv[2] = strdup ("-a");
  637. authpriv[3] = strdup (authproto);
  638. authpriv[4] = strdup ("-u");
  639. authpriv[5] = strdup (secname);
  640. authpriv[6] = strdup ("-A");
  641. authpriv[7] = strdup (authpasswd);
  642. authpriv[8] = strdup ("-x");
  643. authpriv[9] = strdup (privproto);
  644. authpriv[10] = strdup ("-X");
  645. authpriv[11] = strdup (privpasswd);
  646. }
  647. }
  648. }
  649. else {
  650. usage2 (_("Invalid SNMP version"), proto);
  651. }
  652. return OK;
  653. }
  654. /* trim leading whitespace
  655. if there is a leading quote, make sure it balances */
  656. char *
  657. thisarg (char *str)
  658. {
  659. str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
  660. if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
  661. if (strlen (str) == 1 || !strstr (str + 1, "'"))
  662. die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
  663. }
  664. return str;
  665. }
  666. /* if there's a leading quote, advance to the trailing quote
  667. set the trailing quote to '\x0'
  668. if the string continues, advance beyond the comma */
  669. char *
  670. nextarg (char *str)
  671. {
  672. if (strstr (str, "'") == str) {
  673. str[0] = 0;
  674. if (strlen (str) > 1) {
  675. str = strstr (str + 1, "'");
  676. return (++str);
  677. }
  678. else {
  679. return NULL;
  680. }
  681. }
  682. if (strstr (str, ",") == str) {
  683. str[0] = 0;
  684. if (strlen (str) > 1) {
  685. return (++str);
  686. }
  687. else {
  688. return NULL;
  689. }
  690. }
  691. if ((str = strstr (str, ",")) && strlen (str) > 1) {
  692. str[0] = 0;
  693. return (++str);
  694. }
  695. return NULL;
  696. }
  697. void
  698. print_help (void)
  699. {
  700. print_revision (progname, NP_VERSION);
  701. printf (COPYRIGHT, copyright, email);
  702. printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
  703. printf ("\n\n");
  704. print_usage ();
  705. printf (_(UT_HELP_VRSN));
  706. printf (_(UT_EXTRA_OPTS));
  707. printf (_(UT_HOST_PORT), 'p', DEFAULT_PORT);
  708. /* SNMP and Authentication Protocol */
  709. printf (" %s\n", "-n, --next");
  710. printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
  711. printf (" %s\n", "-P, --protocol=[1|2c|3]");
  712. printf (" %s\n", _("SNMP protocol version"));
  713. printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
  714. printf (" %s\n", _("SNMPv3 securityLevel"));
  715. printf (" %s\n", "-a, --authproto=[MD5|SHA]");
  716. printf (" %s\n", _("SNMPv3 auth proto"));
  717. printf (" %s\n", "-x, --privproto=[DES|AES]");
  718. printf (" %s\n", _("SNMPv3 priv proto (default DES)"));
  719. /* Authentication Tokens*/
  720. printf (" %s\n", "-C, --community=STRING");
  721. printf (" %s ", _("Optional community string for SNMP communication"));
  722. printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
  723. printf (" %s\n", "-U, --secname=USERNAME");
  724. printf (" %s\n", _("SNMPv3 username"));
  725. printf (" %s\n", "-A, --authpassword=PASSWORD");
  726. printf (" %s\n", _("SNMPv3 authentication password"));
  727. printf (" %s\n", "-X, --privpasswd=PASSWORD");
  728. printf (" %s\n", _("SNMPv3 privacy password"));
  729. /* OID Stuff */
  730. printf (" %s\n", "-o, --oid=OID(s)");
  731. printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
  732. printf (" %s\n", "-m, --miblist=STRING");
  733. printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
  734. printf (" %s\n", _("for symbolic OIDs.)"));
  735. printf (" %s\n", "-d, --delimiter=STRING");
  736. printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
  737. printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
  738. printf (" %s\n", _("to be the data that should be used in the evaluation."));
  739. /* Tests Against Integers */
  740. printf (" %s\n", "-w, --warning=THRESHOLD(s)");
  741. printf (" %s\n", _("Warning threshold range(s)"));
  742. printf (" %s\n", "-c, --critical=THRESHOLD(s)");
  743. printf (" %s\n", _("Critical threshold range(s)"));
  744. /* Tests Against Strings */
  745. printf (" %s\n", "-s, --string=STRING");
  746. printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
  747. printf (" %s\n", "-r, --ereg=REGEX");
  748. printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
  749. printf (" %s\n", "-R, --eregi=REGEX");
  750. printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
  751. printf (" %s\n", "-l, --label=STRING");
  752. printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
  753. /* Output Formatting */
  754. printf (" %s\n", "-u, --units=STRING");
  755. printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
  756. printf (" %s\n", "-D, --output-delimiter=STRING");
  757. printf (" %s\n", _("Separates output on multiple OID requests"));
  758. printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
  759. printf (" %s\n", "-e, --retries=INTEGER");
  760. printf (" %s\n", _("Number of retries to be used in the requests"));
  761. printf (_(UT_VERBOSE));
  762. printf ("\n");
  763. printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
  764. printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
  765. printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
  766. printf ("\n");
  767. printf ("%s\n", _("Notes:"));
  768. printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
  769. printf (" %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
  770. printf(" -%s", _(UT_THRESHOLDS_NOTES));
  771. printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
  772. printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
  773. printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
  774. printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
  775. #ifdef NP_EXTRA_OPTS
  776. printf (" -%s", _(UT_EXTRA_OPTS_NOTES));
  777. #endif
  778. printf (_(UT_SUPPORT));
  779. }
  780. void
  781. print_usage (void)
  782. {
  783. printf (_("Usage:"));
  784. printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
  785. printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
  786. printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
  787. printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
  788. printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");
  789. }