check_nntp.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /******************************************************************************
  2. *
  3. * CHECK_NNTP.C
  4. *
  5. * Program: NNTP plugin for Nagios
  6. * License: GPL
  7. * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
  8. *
  9. * $Id$
  10. *
  11. * Description:
  12. *
  13. * This plugin will attempt to open an NNTP connection with the host.
  14. * Successul connects return STATE_OK, refusals and timeouts return
  15. * STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful
  16. * connects, but incorrect reponse messages from the host result in
  17. * STATE_WARNING return values. An invalid newsgroup (if the -g
  18. * option is used) results in a STATE_WARNING value.
  19. *
  20. * License Information:
  21. *
  22. * This program is free software; you can redistribute it and/or modify
  23. * it under the terms of the GNU General Public License as published by
  24. * the Free Software Foundation; either version 2 of the License, or
  25. * (at your option) any later version.
  26. *
  27. * This program is distributed in the hope that it will be useful,
  28. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30. * GNU General Public License for more details.
  31. *
  32. * You should have received a copy of the GNU General Public License
  33. * along with this program; if not, write to the Free Software
  34. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  35. *
  36. *****************************************************************************/
  37. #include "config.h"
  38. #include "common.h"
  39. #include "netutils.h"
  40. #include "utils.h"
  41. #define PROGNAME "check_nntp"
  42. #define PORT 119
  43. #define EXPECT1A "200" /* posting allowed */
  44. #define EXPECT1B "201" /* posting not allowed */
  45. #define EXPECT "NNTP"
  46. #define QUIT "QUIT\r\n"
  47. #define MODEREADER "MODE READER\r\n"
  48. int process_arguments (int, char **);
  49. int call_getopt (int, char **);
  50. int validate_arguments (void);
  51. int check_disk (int usp, int free_disk);
  52. void print_help (void);
  53. void print_usage (void);
  54. int server_port = PORT;
  55. char *server_expect = NULL;
  56. char *server_address = NULL;
  57. char *newsgroup = NULL;
  58. int check_newsgroup = FALSE;
  59. int send_modereader = FALSE;
  60. int warning_time = 0;
  61. int check_warning_time = FALSE;
  62. int critical_time = 0;
  63. int check_critical_time = FALSE;
  64. int verbose = FALSE;
  65. int
  66. main (int argc, char **argv)
  67. {
  68. char buffer[MAX_INPUT_BUFFER] = "";
  69. int sd;
  70. int result;
  71. int recv_result;
  72. if (process_arguments (argc, argv) != OK)
  73. usage ("Invalid command arguments supplied\n");
  74. /* initialize alarm signal handling */
  75. signal (SIGALRM, socket_timeout_alarm_handler);
  76. /* set socket timeout */
  77. alarm (socket_timeout);
  78. /* try to connect to the host at the given port number */
  79. time (&start_time);
  80. result = my_tcp_connect (server_address, server_port, &sd);
  81. /* we connected */
  82. if (result == STATE_OK) {
  83. /* watch for the NNTP connection string */
  84. recv_result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
  85. /* return a WARNING status if we couldn't read any data */
  86. if (recv_result == -1) {
  87. printf ("recv() failed\n");
  88. result = STATE_WARNING;
  89. }
  90. else {
  91. /* strip carriage returns from buffer */
  92. strip (buffer);
  93. /* make sure we find the response we are looking for */
  94. if (strstr (buffer, EXPECT1A) != buffer
  95. && strstr (buffer, EXPECT1B) != buffer) {
  96. printf ("Invalid NNTP response received from host: %s\n", buffer);
  97. result = STATE_WARNING;
  98. }
  99. /* optionally send mode reader */
  100. /* added 2000-09-18 by Andreas M. Kirchwitz <amk@krell.snafu.de> including some other minor fixes */
  101. if (send_modereader == TRUE) {
  102. send (sd, MODEREADER, strlen (MODEREADER), 0);
  103. recv_result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
  104. if (recv_result == -1)
  105. strcpy (buffer, "");
  106. else
  107. buffer[recv_result] = 0;
  108. strip (buffer);
  109. if ((strstr (buffer, EXPECT1A) != buffer)
  110. && (strstr (buffer, EXPECT1B) != buffer)) {
  111. printf ("Unexpected NNTP response received from host");
  112. result = STATE_WARNING;
  113. }
  114. }
  115. if (server_expect && !strstr (buffer, server_expect)) {
  116. printf ("Invalid NNTP header received from host: %s\n", buffer);
  117. result = STATE_WARNING;
  118. }
  119. if (check_newsgroup == TRUE) {
  120. sprintf (buffer, "GROUP %s\r\n", newsgroup);
  121. send (sd, buffer, strlen (buffer), 0);
  122. recv_result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
  123. if (recv_result == -1)
  124. strcpy (buffer, "");
  125. else
  126. buffer[recv_result] = 0;
  127. strip (buffer);
  128. if (strstr (buffer, "211") != buffer) {
  129. printf ("NNTP problem - newsgroup '%s' not found\n", newsgroup);
  130. result = STATE_WARNING;
  131. }
  132. }
  133. if (result == STATE_OK) {
  134. time (&end_time);
  135. if (check_critical_time == TRUE
  136. && (end_time - start_time) > critical_time) result =
  137. STATE_CRITICAL;
  138. else if (check_warning_time == TRUE
  139. && (end_time - start_time) > warning_time) result =
  140. STATE_WARNING;
  141. if (verbose)
  142. printf ("NNTP %s - %d sec. response time, %s\n",
  143. (result == STATE_OK) ? "ok" : "problem",
  144. (int) (end_time - start_time), buffer);
  145. else
  146. printf ("NNTP %s - %d second response time\n",
  147. (result == STATE_OK) ? "ok" : "problem",
  148. (int) (end_time - start_time));
  149. }
  150. }
  151. /* close the connection */
  152. send (sd, QUIT, strlen (QUIT), 0);
  153. close (sd);
  154. }
  155. /* reset the alarm timeout */
  156. alarm (0);
  157. return result;
  158. }
  159. /* process command-line arguments */
  160. int
  161. process_arguments (int argc, char **argv)
  162. {
  163. int c;
  164. if (argc < 2)
  165. return ERROR;
  166. for (c = 1; c < argc; c++) {
  167. if (strcmp ("-to", argv[c]) == 0)
  168. strcpy (argv[c], "-t");
  169. else if (strcmp ("-wt", argv[c]) == 0)
  170. strcpy (argv[c], "-w");
  171. else if (strcmp ("-ct", argv[c]) == 0)
  172. strcpy (argv[c], "-c");
  173. }
  174. c = 0;
  175. while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
  176. if (is_option (argv[c]))
  177. continue;
  178. if (server_address == NULL) {
  179. if (is_host (argv[c])) {
  180. server_address = argv[c];
  181. }
  182. else {
  183. usage ("Invalid host name");
  184. }
  185. }
  186. }
  187. if (server_address == NULL)
  188. server_address = strscpy (NULL, "127.0.0.1");
  189. /* if (server_expect==NULL) */
  190. /* server_expect=strscpy(NULL,EXPECT); */
  191. return validate_arguments ();
  192. }
  193. int
  194. call_getopt (int argc, char **argv)
  195. {
  196. int c, i = 0;
  197. #ifdef HAVE_GETOPT_H
  198. int option_index = 0;
  199. static struct option long_options[] = {
  200. {"hostname", required_argument, 0, 'H'},
  201. {"expect", required_argument, 0, 'e'},
  202. {"critical", required_argument, 0, 'c'},
  203. {"warning", required_argument, 0, 'w'},
  204. {"port", required_argument, 0, 'P'},
  205. {"modereader", required_argument, 0, 'M'},
  206. {"verbose", no_argument, 0, 'v'},
  207. {"version", no_argument, 0, 'V'},
  208. {"help", no_argument, 0, 'h'},
  209. {0, 0, 0, 0}
  210. };
  211. #endif
  212. while (1) {
  213. #ifdef HAVE_GETOPT_H
  214. c =
  215. getopt_long (argc, argv, "+hVMvt:p:e:c:w:H:", long_options,
  216. &option_index);
  217. #else
  218. c = getopt (argc, argv, "+?hVMvt:p:e:c:w:H:");
  219. #endif
  220. i++;
  221. if (c == -1 || c == EOF || c == 1)
  222. break;
  223. switch (c) {
  224. case 't':
  225. case 'p':
  226. case 'e':
  227. case 'c':
  228. case 'w':
  229. case 'H':
  230. i++;
  231. }
  232. switch (c) {
  233. case 'H': /* hostname */
  234. if (is_host (optarg)) {
  235. server_address = optarg;
  236. }
  237. else {
  238. usage ("Invalid host name\n");
  239. }
  240. break;
  241. case 'p': /* port */
  242. if (is_intpos (optarg)) {
  243. server_port = atoi (optarg);
  244. }
  245. else {
  246. usage ("Server port must be a positive integer\n");
  247. }
  248. break;
  249. case 'M': /* mode reader */
  250. send_modereader = TRUE;
  251. break;
  252. case 'e': /* expect */
  253. server_expect = optarg;
  254. break;
  255. case 'g': /* newsgroup */
  256. newsgroup = optarg;
  257. check_newsgroup = TRUE;
  258. break;
  259. case 'c': /* critical time threshold */
  260. if (is_intnonneg (optarg)) {
  261. critical_time = atoi (optarg);
  262. check_critical_time = TRUE;
  263. }
  264. else {
  265. usage ("Critical time must be a nonnegative integer\n");
  266. }
  267. break;
  268. case 'w': /* warning time threshold */
  269. if (is_intnonneg (optarg)) {
  270. warning_time = atoi (optarg);
  271. check_warning_time = TRUE;
  272. }
  273. else {
  274. usage ("Warning time must be a nonnegative integer\n");
  275. }
  276. break;
  277. case 'v': /* verbose */
  278. verbose = TRUE;
  279. break;
  280. case 't': /* timeout */
  281. if (is_intnonneg (optarg)) {
  282. socket_timeout = atoi (optarg);
  283. }
  284. else {
  285. usage ("Time interval must be a nonnegative integer\n");
  286. }
  287. break;
  288. case 'V': /* version */
  289. print_revision (PROGNAME, "$Revision$");
  290. exit (STATE_OK);
  291. case 'h': /* help */
  292. print_help ();
  293. exit (STATE_OK);
  294. case '?': /* help */
  295. usage ("Invalid argument\n");
  296. }
  297. }
  298. return i;
  299. }
  300. int
  301. validate_arguments (void)
  302. {
  303. return OK;
  304. }
  305. void
  306. print_help (void)
  307. {
  308. print_revision (PROGNAME, "$Revision$");
  309. printf
  310. ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
  311. "This plugin tests the NNTP service on the specified host.\n\n");
  312. print_usage ();
  313. printf
  314. ("\nOptions:\n"
  315. " -H, --hostname=STRING or IPADDRESS\n"
  316. " Check server on the indicated host\n"
  317. " -p, --port=INTEGER\n"
  318. " Make connection on the indicated port (default: %d)\n"
  319. " -e, --expect=STRING\n"
  320. " String to expect in first line of server response (default: %s)\n"
  321. " -g, --group=STRING\n"
  322. " Newsgroup to poll\n"
  323. " -w, --warning=INTEGER\n"
  324. " Seconds necessary to result in a warning status\n"
  325. " -c, --critical=INTEGER\n"
  326. " Seconds necessary to result in a critical status\n"
  327. " -t, --timeout=INTEGER\n"
  328. " Seconds before connection attempt times out (default: %d)\n"
  329. " -M\n"
  330. " Send \"MODE READER\" after initial connect.\n"
  331. " -v, --verbose\n"
  332. " Print extra information (command-line use only)\n"
  333. " -h, --help\n"
  334. " Print detailed help screen\n"
  335. " -V, --version\n"
  336. " Print version information\n\n",
  337. PORT, EXPECT, DEFAULT_SOCKET_TIMEOUT);
  338. support ();
  339. }
  340. void
  341. print_usage (void)
  342. {
  343. printf
  344. ("Usage: %s -H host [-e expect] [-g group] [-p port] [-w warn] [-c crit]\n"
  345. " [-t timeout] [-v]\n"
  346. " %s --help\n"
  347. " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
  348. }