1 /*
2 ex: set tabstop=4 shiftwidth=4 autoindent:
3 +-------------------------------------------------------------------------+
4 | Copyright (C) 2004-2021 The Cacti Group |
5 | |
6 | This program is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2.1 of the License, or (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 Lesser General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with this library; if not, write to the Free Software |
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
19 | 02110-1301, USA |
20 | |
21 +-------------------------------------------------------------------------+
22 | spine: a backend data gatherer for cacti |
23 +-------------------------------------------------------------------------+
24 | This poller would not have been possible without: |
25 | - Larry Adams (current development and enhancements) |
26 | - Rivo Nurges (rrd support, mysql poller cache, misc functions) |
27 | - RTG (core poller code, pthreads, snmp, autoconf examples) |
28 | - Brady Alleman/Doug Warner (threading ideas, implimentation details) |
29 +-------------------------------------------------------------------------+
30 | - Cacti - http://www.cacti.net/ |
31 +-------------------------------------------------------------------------+
32 */
33
34 #include "common.h"
35 #include "spine.h"
36
37 extern int pending_threads;
38
39 /*! \fn void *child(void *arg)
40 * \brief function is called via the fork command and initiates a poll of a host
41 * \param arg a pointer to an integer point to the host_id to be polled
42 *
43 * This function will call the primary Spine polling function to poll a host
44 * and then reduce the number of active threads by one so that the next host
45 * can be polled.
46 *
47 */
child(void * arg)48 void *child(void *arg) {
49 int host_id;
50 int host_thread;
51 int last_host_thread;
52 int host_data_ids;
53 int host_errors;
54 double host_time_double;
55 char host_time[SMALL_BUFSIZE];
56 int a_threads_value;
57
58 host_errors = 0;
59
60 poller_thread_t poller_details = *(poller_thread_t*) arg;
61 host_id = poller_details.host_id;
62 host_thread = poller_details.host_thread;
63 last_host_thread = poller_details.last_host_thread;
64 host_data_ids = poller_details.host_data_ids;
65 host_time_double = poller_details.host_time_double;
66 snprintf(host_time, SMALL_BUFSIZE, "%s", poller_details.host_time);
67
68 /* Allows main thread to proceed with creation of other threads */
69 sem_post(poller_details.thread_init_sem);
70
71 if (is_debug_device(host_id)) {
72 SPINE_LOG(("DEBUG: In Poller, About to Start Polling of Device for Device ID %i", host_id));
73 } else {
74 SPINE_LOG_DEBUG(("DEBUG: In Poller, About to Start Polling of Device for Device ID %i", host_id));
75 }
76
77 poll_host(host_id, host_thread, last_host_thread, host_data_ids, host_time, &host_errors, host_time_double);
78
79 sem_post(&active_threads);
80
81 sem_getvalue(&active_threads, &a_threads_value);
82
83 if (is_debug_device(host_id)) {
84 SPINE_LOG(("DEBUG: The Value of Active Threads is %i for Device ID %i", set.threads - a_threads_value, host_id));
85 } else {
86 SPINE_LOG_DEBUG(("DEBUG: The Value of Active Threads is %i for Device ID %i", set.threads - a_threads_value, host_id));
87 }
88
89 thread_mutex_lock(LOCK_PEND);
90 pending_threads--;
91 poller_details.complete = TRUE;
92
93 SPINE_LOG_MEDIUM(("Active Threads is %i, Pending is %i", set.threads - a_threads_value, pending_threads));
94 thread_mutex_unlock(LOCK_PEND);
95
96 /* end the thread */
97 pthread_exit(0);
98
99 exit(0);
100 }
101
102 /*! \fn void poll_host(int host_id, int host_thread, int last_host_thread, int host_data_ids, char *host_time, int *host_errors, double *host_time_double)
103 * \brief core Spine function that polls a host
104 * \param host_id integer value for the host_id from the hosts table in Cacti
105 *
106 * This function is core to Spine. It will take a host_id and then poll it.
107 *
108 * Prior to the poll, the system will ping the host to verifiy that it is up.
109 * In addition, the system will check to see if any reindexing of data query's
110 * is required.
111 *
112 * If reindexing is required, the Cacti poller.php function will spawn that
113 * reindexing process.
114 *
115 * In the case of hosts that require reindexing because of a sysUptime
116 * rollback, Spine will store an unknown (NaN) value for all objects to prevent
117 * spikes in the graphs.
118 *
119 * With regard to snmp calls, if the host has multiple snmp agents running
120 * Spine will re-initialize the snmp session and poll under those new ports
121 * as the host poller_items table dictates.
122 *
123 */
poll_host(int host_id,int host_thread,int last_host_thread,int host_data_ids,char * host_time,int * host_errors,double host_time_double)124 void poll_host(int host_id, int host_thread, int last_host_thread, int host_data_ids, char *host_time, int *host_errors, double host_time_double) {
125 char query1[BUFSIZE];
126 char query2[BIG_BUFSIZE];
127 char *query3 = NULL;
128 char query4[BUFSIZE];
129 char query5[BUFSIZE];
130 char query6[BUFSIZE];
131 char query8[BUFSIZE];
132 char query9[BUFSIZE];
133 char query10[BUFSIZE];
134 char query11[BUFSIZE];
135 char *query12 = NULL;
136 char posuffix[BUFSIZE];
137
138 int query1_len = 0;
139 int query2_len = 0;
140 int query4_len = 0;
141 int query5_len = 0;
142 int query6_len = 0;
143 int query8_len = 0;
144 int query9_len = 0;
145 int query10_len = 0;
146 int query11_len = 0;
147 int posuffix_len = 0;
148
149 char sysUptime[BUFSIZE];
150 char result_string[RESULTS_BUFFER+SMALL_BUFSIZE];
151 int result_length;
152 char temp_result[RESULTS_BUFFER];
153 int errors = 0;
154 int *buf_errors;
155 int *buf_size;
156 char *error_string;
157 int error_len = 0;
158
159 int num_rows;
160 int assert_fail = FALSE;
161 int reindex_err = FALSE;
162 int spike_kill = FALSE;
163 int rows_processed = 0;
164 int i = 0;
165 int j = 0;
166 int k = 0;
167 int num_oids = 0;
168 int snmp_poller_items = 0;
169 size_t out_buffer;
170 int php_process;
171
172 char *poll_result = NULL;
173 char update_sql[BIG_BUFSIZE];
174 char temp_poll_result[BUFSIZE];
175 char temp_arg1[BUFSIZE];
176 char limits[SMALL_BUFSIZE];
177
178 int num_snmp_agents = 0;
179 int last_snmp_version = 0;
180 int last_snmp_port = 0;
181 char last_snmp_community[50];
182 char last_snmp_username[50];
183 char last_snmp_password[50];
184 char last_snmp_auth_protocol[5];
185 char last_snmp_priv_passphrase[200];
186 char last_snmp_priv_protocol[7];
187 char last_snmp_context[65];
188 char last_snmp_engine_id[30];
189 double poll_time = get_time_as_double();
190 double thread_start = 0;
191 double thread_end = 0;
192
193 /* reindex shortcuts to speed polling */
194 int previous_assert_failure = FALSE;
195 int last_data_query_id = 0;
196 int perform_assert = TRUE;
197 int new_buffer = TRUE;
198 int ignore_sysinfo = TRUE;
199 int buf_length = 0;
200
201 pool_t *local_cnn;
202 pool_t *remote_cnn;
203
204 reindex_t *reindex;
205 host_t *host;
206 ping_t *ping;
207 target_t *poller_items;
208 snmp_oids_t *snmp_oids;
209
210 error_string = malloc(DBL_BUFSIZE);
211 buf_size = malloc(sizeof(int));
212 buf_errors = malloc(sizeof(int));
213
214 *buf_size = 0;
215 *buf_errors = 0;
216
217 MYSQL mysql;
218 MYSQL mysqlr;
219 MYSQL mysqlt;
220 MYSQL_RES *result;
221 MYSQL_ROW row;
222
223 //db_connect(LOCAL, &mysql);
224 local_cnn = db_get_connection(LOCAL);
225 mysql = local_cnn->mysql;
226
227 if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) {
228 remote_cnn = db_get_connection(REMOTE);
229 mysqlr = remote_cnn->mysql;
230 }
231
232 /* allocate host and ping structures with appropriate values */
233 if (!(host = (host_t *) malloc(sizeof(host_t)))) {
234 die("ERROR: Fatal malloc error: poller.c host struct!");
235 }
236
237 /* set zeros */
238 memset(host, 0, sizeof(host_t));
239
240 if (!(ping = (ping_t *) malloc(sizeof(ping_t)))) {
241 die("ERROR: Fatal malloc error: poller.c ping struct!");
242 }
243
244 /* set zeros */
245 memset(ping, 0, sizeof(ping_t));
246
247 if (!(reindex = (reindex_t *) malloc(sizeof(reindex_t)))) {
248 die("ERROR: Fatal malloc error: poller.c reindex poll!");
249 }
250 memset(reindex, 0, sizeof(reindex_t));
251
252 /* determine the SQL limits using the poller instructions */
253 if (host_data_ids > 0) {
254 snprintf(limits, SMALL_BUFSIZE, "LIMIT %i, %i", host_data_ids * (host_thread - 1), host_data_ids);
255 } else {
256 limits[0] = '\0';
257 }
258
259 /* single polling interval query for items */
260 if (set.poller_id == 0) {
261 snprintf(query1, BUFSIZE,
262 "SELECT action, hostname, snmp_community, "
263 "snmp_version, snmp_username, snmp_password, "
264 "rrd_name, rrd_path, arg1, arg2, arg3, local_data_id, "
265 "rrd_num, snmp_port, snmp_timeout, "
266 "snmp_auth_protocol, snmp_priv_passphrase, snmp_priv_protocol, snmp_context, snmp_engine_id "
267 " FROM poller_item"
268 " WHERE host_id = %i"
269 " AND deleted = ''"
270 " ORDER BY snmp_port %s", host_id, limits);
271
272 /* host structure for uptime checks */
273 snprintf(query2, BIG_BUFSIZE,
274 "SELECT id, hostname, snmp_community, snmp_version, "
275 "snmp_username, snmp_password, snmp_auth_protocol, "
276 "snmp_priv_passphrase, snmp_priv_protocol, snmp_context, snmp_engine_id, snmp_port, snmp_timeout, max_oids, "
277 "availability_method, ping_method, ping_port, ping_timeout, ping_retries, "
278 "status, status_event_count, UNIX_TIMESTAMP(status_fail_date), "
279 "UNIX_TIMESTAMP(status_rec_date), status_last_error, "
280 "min_time, max_time, cur_time, avg_time, "
281 "total_polls, failed_polls, availability, snmp_sysUpTimeInstance, snmp_sysDescr, snmp_sysObjectID, "
282 "snmp_sysContact, snmp_sysName, snmp_sysLocation"
283 " FROM host"
284 " WHERE id = %i"
285 " AND deleted = ''", host_id);
286
287 /* data query structure for reindex detection */
288 snprintf(query4, BUFSIZE,
289 "SELECT data_query_id, action, op, assert_value, arg1"
290 " FROM poller_reindex"
291 " WHERE host_id = %i", host_id);
292
293 /* multiple polling interval query for items */
294 snprintf(query5, BUFSIZE,
295 "SELECT action, hostname, snmp_community, "
296 "snmp_version, snmp_username, snmp_password, "
297 "rrd_name, rrd_path, arg1, arg2, arg3, local_data_id, "
298 "rrd_num, snmp_port, snmp_timeout, "
299 "snmp_auth_protocol, snmp_priv_passphrase, snmp_priv_protocol, snmp_context, snmp_engine_id "
300 " FROM poller_item"
301 " WHERE host_id = %i"
302 " AND rrd_next_step <= 0"
303 " ORDER by snmp_port %s", host_id, limits);
304
305 /* query to setup the next polling interval in cacti */
306 snprintf(query6, BUFSIZE,
307 "UPDATE poller_item"
308 " SET rrd_next_step = IF(rrd_step = %i, 0, IF(rrd_next_step - %i < 0, rrd_step, rrd_next_step - %i))"
309 " WHERE host_id = %i", set.poller_interval, set.poller_interval, set.poller_interval, host_id);
310
311 /* query to add output records to the poller output table */
312 snprintf(query8, BUFSIZE,
313 "INSERT INTO poller_output"
314 " (local_data_id, rrd_name, time, output) VALUES");
315
316 /* query suffix to add rows to the poller output table */
317 snprintf(posuffix, BUFSIZE,
318 " ON DUPLICATE KEY UPDATE output=VALUES(output)");
319
320 /* number of agent's count for single polling interval */
321 snprintf(query9, BUFSIZE,
322 "SELECT snmp_port, count(snmp_port)"
323 " FROM poller_item"
324 " WHERE host_id = %i"
325 " GROUP BY snmp_port %s", host_id, limits);
326
327 /* number of agent's count for multiple polling intervals */
328 snprintf(query10, BUFSIZE,
329 "SELECT snmp_port, count(snmp_port)"
330 " FROM poller_item"
331 " WHERE host_id = %i"
332 " AND rrd_next_step <= 0"
333 " GROUP BY snmp_port %s", host_id, limits);
334 } else {
335 snprintf(query1, BUFSIZE,
336 "SELECT action, hostname, snmp_community, "
337 "snmp_version, snmp_username, snmp_password, "
338 "rrd_name, rrd_path, arg1, arg2, arg3, local_data_id, "
339 "rrd_num, snmp_port, snmp_timeout, "
340 "snmp_auth_protocol, snmp_priv_passphrase, snmp_priv_protocol, snmp_context, snmp_engine_id "
341 " FROM poller_item"
342 " WHERE host_id = %i"
343 " AND poller_id=%i"
344 " ORDER BY snmp_port %s", host_id, set.poller_id, limits);
345
346 /* host structure for uptime checks */
347 snprintf(query2, BIG_BUFSIZE,
348 "SELECT id, hostname, snmp_community, snmp_version, "
349 "snmp_username, snmp_password, snmp_auth_protocol, "
350 "snmp_priv_passphrase, snmp_priv_protocol, snmp_context, snmp_engine_id, snmp_port, snmp_timeout, max_oids, "
351 "availability_method, ping_method, ping_port, ping_timeout, ping_retries, "
352 "status, status_event_count, UNIX_TIMESTAMP(status_fail_date), "
353 "UNIX_TIMESTAMP(status_rec_date), status_last_error, "
354 "min_time, max_time, cur_time, avg_time, "
355 "total_polls, failed_polls, availability, snmp_sysUpTimeInstance, snmp_sysDescr, snmp_sysObjectID, "
356 "snmp_sysContact, snmp_sysName, snmp_sysLocation"
357 " FROM host"
358 " WHERE id = %i"
359 " AND deleted = ''", host_id);
360
361 /* data query structure for reindex detection */
362 snprintf(query4, BUFSIZE,
363 "SELECT data_query_id, action, op, assert_value, arg1"
364 " FROM poller_reindex"
365 " WHERE host_id = %i", host_id);
366
367 /* multiple polling interval query for items */
368 snprintf(query5, BUFSIZE,
369 "SELECT action, hostname, snmp_community, "
370 "snmp_version, snmp_username, snmp_password, "
371 "rrd_name, rrd_path, arg1, arg2, arg3, local_data_id, "
372 "rrd_num, snmp_port, snmp_timeout, "
373 "snmp_auth_protocol, snmp_priv_passphrase, snmp_priv_protocol, snmp_context, snmp_engine_id "
374 " FROM poller_item"
375 " WHERE host_id = %i"
376 " AND rrd_next_step <= 0"
377 " AND poller_id = %i"
378 " ORDER by snmp_port %s", host_id, set.poller_id, limits);
379
380 /* query to setup the next polling interval in cacti */
381 snprintf(query6, BUFSIZE,
382 "UPDATE poller_item"
383 " SET rrd_next_step = IF(rrd_step = %i, 0, IF(rrd_next_step - %i < 0, rrd_step, rrd_next_step - %i))"
384 " WHERE host_id = %i"
385 " AND poller_id = %i", set.poller_interval, set.poller_interval, set.poller_interval, host_id, set.poller_id);
386
387 /* query to add output records to the poller output table */
388 snprintf(query8, BUFSIZE,
389 "INSERT INTO poller_output"
390 " (local_data_id, rrd_name, time, output) VALUES");
391
392 /* query suffix to add rows to the poller output table */
393 snprintf(posuffix, BUFSIZE,
394 " ON DUPLICATE KEY UPDATE output=VALUES(output)");
395
396 /* number of agent's count for single polling interval */
397 snprintf(query9, BUFSIZE,
398 "SELECT snmp_port, count(snmp_port)"
399 " FROM poller_item"
400 " WHERE host_id = %i"
401 " AND poller_id = %i"
402 " GROUP BY snmp_port %s", host_id, set.poller_id, limits);
403
404 /* number of agent's count for multiple polling intervals */
405 snprintf(query10, BUFSIZE,
406 "SELECT snmp_port, count(snmp_port)"
407 " FROM poller_item"
408 " WHERE host_id = %i"
409 " AND rrd_next_step <= 0"
410 " AND poller_id = %i"
411 " GROUP BY snmp_port %s", host_id, set.poller_id, limits);
412 }
413
414 /* query to add output records to the poller output table */
415 snprintf(query11, BUFSIZE,
416 "INSERT INTO poller_output_boost"
417 " (local_data_id, rrd_name, time, output) VALUES");
418
419 query1_len = strlen(query1);
420 query2_len = strlen(query2);
421 query4_len = strlen(query4);
422 query5_len = strlen(query5);
423 query6_len = strlen(query6);
424 query8_len = strlen(query8);
425 query9_len = strlen(query9);
426 query10_len = strlen(query10);
427 query11_len = strlen(query11);
428 posuffix_len = strlen(posuffix);
429
430 /* initialize the ping structure variables */
431 snprintf(ping->ping_status, 50, "down");
432 snprintf(ping->ping_response, SMALL_BUFSIZE, "Ping not performed due to setting.");
433 snprintf(ping->snmp_status, 50, "down");
434 snprintf(ping->snmp_response, SMALL_BUFSIZE, "SNMP not performed due to setting or ping result");
435
436 /* if the host is a real host. Note host_id=0 is not host based data source */
437 if (host_id) {
438 /* get data about this host */
439 if ((result = db_query(&mysql, LOCAL, query2)) != 0) {
440 num_rows = mysql_num_rows(result);
441
442 if (num_rows != 1) {
443 mysql_free_result(result);
444 db_release_connection(LOCAL, local_cnn->id);
445
446 if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) {
447 db_release_connection(REMOTE, remote_cnn->id);
448 }
449
450 return;
451 }
452
453 /* fetch the result */
454 row = mysql_fetch_row(result);
455
456 if (row) {
457 /* initialize variables first */
458 host->id = 0; // 0
459 host->hostname[0] = '\0'; // 1
460 host->snmp_session = NULL; // -
461 host->snmp_community[0] = '\0'; // 2
462 host->snmp_version = 1; // 3
463 host->snmp_username[0] = '\0'; // 4
464 host->snmp_password[0] = '\0'; // 5
465 host->snmp_auth_protocol[0] = '\0'; // 6
466 host->snmp_priv_passphrase[0] = '\0'; // 7
467 host->snmp_priv_protocol[0] = '\0'; // 8
468 host->snmp_context[0] = '\0'; // 9
469 host->snmp_engine_id[0] = '\0'; // 10
470 host->snmp_port = 161; // 11
471 host->snmp_timeout = 500; // 12
472 host->snmp_retries = set.snmp_retries; // -
473 host->max_oids = 10; // 13
474 host->availability_method = 0; // 14
475 host->ping_method = 0; // 15
476 host->ping_port = 23; // 16
477 host->ping_timeout = 500; // 17
478 host->ping_retries = 2; // 18
479 host->status = HOST_UP; // 19
480 host->status_event_count = 0; // 20
481 host->status_fail_date[0] = '\0'; // 21
482 host->status_rec_date[0] = '\0'; // 22
483 host->status_last_error[0] = '\0'; // 23
484 host->min_time = 0; // 24
485 host->max_time = 0; // 25
486 host->cur_time = 0; // 26
487 host->avg_time = 0; // 27
488 host->total_polls = 0; // 28
489 host->failed_polls = 0; // 29
490 host->availability = 100; // 30
491 host->snmp_sysUpTimeInstance = 0; // 31
492 host->snmp_sysDescr[0] = '\0'; // 32
493 host->snmp_sysObjectID[0] = '\0'; // 33
494 host->snmp_sysContact[0] = '\0'; // 34
495 host->snmp_sysName[0] = '\0'; // 35
496 host->snmp_sysLocation[0] = '\0'; // 36
497
498 /* populate host structure */
499 host->ignore_host = FALSE;
500 if (row[0] != NULL) host->id = atoi(row[0]);
501
502 if (row[1] != NULL) STRNCOPY(host->hostname, row[1]);
503 if (row[2] != NULL) STRNCOPY(host->snmp_community, row[2]);
504
505 if (row[3] != NULL) host->snmp_version = atoi(row[3]);
506
507 if (row[4] != NULL) STRNCOPY(host->snmp_username, row[4]);
508 if (row[5] != NULL) STRNCOPY(host->snmp_password, row[5]);
509 if (row[6] != NULL) STRNCOPY(host->snmp_auth_protocol, row[6]);
510 if (row[7] != NULL) STRNCOPY(host->snmp_priv_passphrase, row[7]);
511 if (row[8] != NULL) STRNCOPY(host->snmp_priv_protocol, row[8]);
512 if (row[9] != NULL) STRNCOPY(host->snmp_context, row[9]);
513 if (row[10] != NULL) STRNCOPY(host->snmp_engine_id, row[10]);
514
515 if (row[11] != NULL) host->snmp_port = atoi(row[11]);
516 if (row[12] != NULL) host->snmp_timeout = atoi(row[12]);
517 if (row[13] != NULL) host->max_oids = atoi(row[13]);
518
519 if (row[14] != NULL) host->availability_method = atoi(row[14]);
520 if (row[15] != NULL) host->ping_method = atoi(row[15]);
521 if (row[16] != NULL) host->ping_port = atoi(row[16]);
522 if (row[17] != NULL) host->ping_timeout = atoi(row[17]);
523 if (row[18] != NULL) host->ping_retries = atoi(row[18]);
524
525 if (row[19] != NULL) host->status = atoi(row[19]);
526 if (row[20] != NULL) host->status_event_count = atoi(row[20]);
527
528 if (row[21] != NULL) STRNCOPY(host->status_fail_date, row[21]);
529 if (row[22] != NULL) STRNCOPY(host->status_rec_date, row[22]);
530
531 if (row[23] != NULL) STRNCOPY(host->status_last_error, row[23]);
532
533 if (row[24] != NULL) host->min_time = atof(row[24]);
534 if (row[25] != NULL) host->max_time = atof(row[25]);
535 if (row[26] != NULL) host->cur_time = atof(row[26]);
536 if (row[27] != NULL) host->avg_time = atof(row[27]);
537 if (row[28] != NULL) host->total_polls = atoi(row[28]);
538 if (row[29] != NULL) host->failed_polls = atoi(row[29]);
539 if (row[30] != NULL) host->availability = atof(row[30]);
540
541 if (row[31] != NULL) host->snmp_sysUpTimeInstance=atoi(row[31]);
542 if (row[32] != NULL) db_escape(&mysql, host->snmp_sysDescr, sizeof(host->snmp_sysDescr), row[32]);
543 if (row[33] != NULL) db_escape(&mysql, host->snmp_sysObjectID, sizeof(host->snmp_sysObjectID), row[33]);
544 if (row[34] != NULL) db_escape(&mysql, host->snmp_sysContact, sizeof(host->snmp_sysContact), row[34]);
545 if (row[35] != NULL) db_escape(&mysql, host->snmp_sysName, sizeof(host->snmp_sysName), row[35]);
546 if (row[36] != NULL) db_escape(&mysql, host->snmp_sysLocation, sizeof(host->snmp_sysLocation), row[36]);
547
548 /* correct max_oid bounds issues */
549 if ((host->max_oids == 0) || (host->max_oids > 100)) {
550 SPINE_LOG(("Device[%i] HT[%i] WARNING: Max OIDS is out of range with value of '%i'. Resetting to default of 5", host_id, host_thread, host->max_oids));
551 host->max_oids = 5;
552 }
553
554 /* free the host result */
555 mysql_free_result(result);
556
557 if (((host->snmp_version >= 1) && (host->snmp_version <= 2) &&
558 (strlen(host->snmp_community) > 0)) ||
559 (host->snmp_version == 3)) {
560 host->snmp_session = snmp_host_init(host->id,
561 host->hostname,
562 host->snmp_version,
563 host->snmp_community,
564 host->snmp_username,
565 host->snmp_password,
566 host->snmp_auth_protocol,
567 host->snmp_priv_passphrase,
568 host->snmp_priv_protocol,
569 host->snmp_context,
570 host->snmp_engine_id,
571 host->snmp_port,
572 host->snmp_timeout);
573 } else {
574 host->snmp_session = NULL;
575 }
576
577 /* perform a check to see if the host is alive by polling it's SysDesc
578 * if the host down from an snmp perspective, don't poll it.
579 * function sets the ignore_host bit */
580 if ((host->availability_method == AVAIL_SNMP) &&
581 (strlen(host->snmp_community) == 0) &&
582 (host->snmp_version < 3)) {
583 host->ignore_host = FALSE;
584 update_host_status(HOST_UP, host, ping, host->availability_method);
585
586 if (is_debug_device(host->id)) {
587 SPINE_LOG(("Device[%i] HT[%i] No host availability check possible for '%s'", host->id, host_thread, host->hostname));
588 } else {
589 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] No host availability check possible for '%s'", host->id, host_thread, host->hostname));
590 }
591 } else {
592 if (ping_host(host, ping) == HOST_UP) {
593 host->ignore_host = FALSE;
594 if (host_thread == 1) {
595 update_host_status(HOST_UP, host, ping, host->availability_method);
596
597 if ((host->availability_method != AVAIL_PING) && (host->availability_method != AVAIL_NONE)) {
598 if (host->snmp_session != NULL) {
599 get_system_information(host, &mysql, 1);
600 ignore_sysinfo = FALSE;
601 }
602 }
603 }
604 } else {
605 host->ignore_host = TRUE;
606 if (host_thread == 1) {
607 update_host_status(HOST_DOWN, host, ping, host->availability_method);
608 }
609 }
610 }
611
612 /* update host table */
613 if (host_thread == 1) {
614 if (!ignore_sysinfo) {
615 if (host->ignore_host != TRUE) {
616 snprintf(update_sql, BIG_BUFSIZE, "UPDATE host "
617 "SET status='%i', status_event_count='%i', status_fail_date=FROM_UNIXTIME(%s),"
618 " status_rec_date=FROM_UNIXTIME(%s), status_last_error='%s', min_time='%f',"
619 " max_time='%f', cur_time='%f', avg_time='%f', total_polls='%i',"
620 " failed_polls='%i', availability='%.4f', snmp_sysDescr='%s', "
621 " snmp_sysObjectID='%s', snmp_sysUpTimeInstance='%u', "
622 " snmp_sysContact='%s', snmp_sysName='%s', snmp_sysLocation='%s' "
623 "WHERE id='%i'",
624 host->status,
625 host->status_event_count,
626 host->status_fail_date,
627 host->status_rec_date,
628 host->status_last_error,
629 host->min_time,
630 host->max_time,
631 host->cur_time,
632 host->avg_time,
633 host->total_polls,
634 host->failed_polls,
635 host->availability,
636 host->snmp_sysDescr,
637 host->snmp_sysObjectID,
638 host->snmp_sysUpTimeInstance,
639 host->snmp_sysContact,
640 host->snmp_sysName,
641 host->snmp_sysLocation,
642 host->id);
643 } else {
644 snprintf(update_sql, BIG_BUFSIZE, "UPDATE host "
645 "SET status='%i', status_event_count='%i', status_fail_date=FROM_UNIXTIME(%s),"
646 " status_rec_date=FROM_UNIXTIME(%s), status_last_error='%s', min_time='%f',"
647 " max_time='%f', cur_time='%f', avg_time='%f', total_polls='%i',"
648 " failed_polls='%i', availability='%.4f' "
649 "WHERE id='%i'",
650 host->status,
651 host->status_event_count,
652 host->status_fail_date,
653 host->status_rec_date,
654 host->status_last_error,
655 host->min_time,
656 host->max_time,
657 host->cur_time,
658 host->avg_time,
659 host->total_polls,
660 host->failed_polls,
661 host->availability,
662 host->id);
663 }
664 } else {
665 snprintf(update_sql, BIG_BUFSIZE, "UPDATE host "
666 "SET status='%i', status_event_count='%i', status_fail_date=FROM_UNIXTIME(%s),"
667 " status_rec_date=FROM_UNIXTIME(%s), status_last_error='%s', min_time='%f',"
668 " max_time='%f', cur_time='%f', avg_time='%f', total_polls='%i',"
669 " failed_polls='%i', availability='%.4f' "
670 "WHERE id='%i'",
671 host->status,
672 host->status_event_count,
673 host->status_fail_date,
674 host->status_rec_date,
675 host->status_last_error,
676 host->min_time,
677 host->max_time,
678 host->cur_time,
679 host->avg_time,
680 host->total_polls,
681 host->failed_polls,
682 host->availability,
683 host->id);
684 }
685
686 db_insert(&mysql, LOCAL, update_sql);
687 }
688 } else {
689 SPINE_LOG(("Device[%i] HT[%i] ERROR: MySQL Returned a Null Device Result", host->id, host_thread));
690 num_rows = 0;
691 host->ignore_host = TRUE;
692 }
693 } else {
694 num_rows = 0;
695 host->ignore_host = TRUE;
696 }
697 } else {
698 host->id = 0;
699 host->max_oids = 1;
700 host->snmp_session = NULL;
701 host->ignore_host = FALSE;
702 }
703
704 /* do the reindex check for this host if not script based */
705 if ((!host->ignore_host) && (host_id)) {
706 if ((result = db_query(&mysql, LOCAL, query4)) != 0) {
707 num_rows = mysql_num_rows(result);
708
709 if (num_rows > 0) {
710 if (is_debug_device(host->id)) {
711 SPINE_LOG(("DEBUG: Device[%i] HT[%i] RECACHE: Processing %i items in the auto reindex cache for '%s'", host->id, host_thread, num_rows, host->hostname));
712 } else {
713 SPINE_LOG_DEBUG(("DEBUG: Device[%i] HT[%i] RECACHE: Processing %i items in the auto reindex cache for '%s'", host->id, host_thread, num_rows, host->hostname));
714 }
715
716 // Cache uptime in case we need it again
717 sysUptime[0] = '\0';
718 while ((row = mysql_fetch_row(result))) {
719 assert_fail = FALSE;
720 reindex_err = FALSE;
721
722 /* initialize the reindex struction */
723 reindex->data_query_id = 0;
724 reindex->action = -1;
725 reindex->op[0] = '\0';
726 reindex->assert_value[0] = '\0';
727 reindex->arg1[0] = '\0';
728
729 if (row[0] != NULL) reindex->data_query_id = atoi(row[0]);
730 if (row[1] != NULL) reindex->action = atoi(row[1]);
731
732 if (row[2] != NULL) snprintf(reindex->op, sizeof(reindex->op), "%s", row[2]);
733
734 if (row[3] != NULL) snprintf(reindex->assert_value, sizeof(reindex->assert_value), "%s", row[3]);
735
736 if (row[4] != NULL) snprintf(reindex->arg1, sizeof(reindex->arg1), "%s", row[4]);
737
738 /* shortcut assertion checks if a data query reindex has already been queued */
739 if ((last_data_query_id == reindex->data_query_id) &&
740 (!previous_assert_failure)) {
741 perform_assert = TRUE;
742 } else if (last_data_query_id != reindex->data_query_id) {
743 last_data_query_id = reindex->data_query_id;
744 perform_assert = TRUE;
745 previous_assert_failure = FALSE;
746 } else {
747 perform_assert = FALSE;
748 }
749
750 poll_result = NULL;
751
752 if (perform_assert) {
753 switch(reindex->action) {
754 case POLLER_ACTION_SNMP: /* snmp */
755 /* if there is no snmp session, don't probe */
756 if (!host->snmp_session) {
757 reindex_err = TRUE;
758 }
759
760 /* check to see if you are checking uptime */
761 if (!reindex_err) {
762 if (strstr(reindex->arg1, ".1.3.6.1.2.1.1.3.0") &&
763 (strlen(sysUptime) > 0)) {
764 if (!(poll_result = (char *) malloc(BUFSIZE))) {
765 die("ERROR: Fatal malloc error: poller.c poll_result");
766 }
767 poll_result[0] = '\0';
768 snprintf(poll_result, BUFSIZE, "%s", sysUptime);
769 } else if (strstr(reindex->arg1, ".1.3.6.1.2.1.1.3.0")) {
770 poll_result = snmp_get(host, reindex->arg1);
771 snprintf(sysUptime, BUFSIZE, "%s", poll_result);
772 } else {
773 poll_result = snmp_get(host, reindex->arg1);
774 }
775
776 if (is_debug_device(host->id)) {
777 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE OID: %s, (assert: %s %s output: %s)", host->id, host_thread, reindex->data_query_id, reindex->arg1, reindex->assert_value, reindex->op, poll_result));
778 } else {
779 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE OID: %s, (assert: %s %s output: %s)", host->id, host_thread, reindex->data_query_id, reindex->arg1, reindex->assert_value, reindex->op, poll_result));
780 }
781 } else {
782 SPINE_LOG(("WARNING: Device[%i] HT[%i] DQ[%i] Reindex Check FAILED: No SNMP Session. If not an SNMP host, don't use Uptime Goes Backwards!", host->id, host_thread, reindex->data_query_id));
783 }
784
785 break;
786 case POLLER_ACTION_SCRIPT: /* script (popen) */
787 poll_result = trim(exec_poll(host, reindex->arg1, reindex->data_query_id, "DQ"));
788 if (is_debug_device(host->id)) {
789 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE CMD: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
790 } else {
791 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE CMD: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
792 }
793
794 break;
795 case POLLER_ACTION_PHP_SCRIPT_SERVER: /* script (php script server) */
796 php_process = php_get_process();
797 poll_result = trim(php_cmd(reindex->arg1, php_process));
798 if (is_debug_device(host->id)) {
799 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE SERVER: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
800 } else {
801 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE SERVER: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
802 }
803
804 break;
805 case POLLER_ACTION_SNMP_COUNT: /* snmp; count items */
806 if (!(poll_result = (char *) malloc(BUFSIZE))) {
807 die("ERROR: Fatal malloc error: poller.c poll_result");
808 }
809 poll_result[0] = '\0';
810
811 snprintf(poll_result, BUFSIZE, "%d", snmp_count(host, reindex->arg1));
812 if (is_debug_device(host->id)) {
813 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE OID COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
814 } else {
815 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE OID COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
816 }
817
818 break;
819 case POLLER_ACTION_SCRIPT_COUNT: /* script (popen); count items by counting line feeds */
820 if (!(poll_result = (char *) malloc(BUFSIZE))) {
821 die("ERROR: Fatal malloc error: poller.c poll_result");
822 }
823 poll_result[0] = '\0';
824
825 snprintf(poll_result, BUFSIZE, "%d", char_count(exec_poll(host, reindex->arg1, reindex->data_query_id, "DQ"), '\n'));
826 if (is_debug_device(host->id)) {
827 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE CMD COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
828 } else {
829 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE CMD COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
830 }
831
832 break;
833 case POLLER_ACTION_PHP_SCRIPT_SERVER_COUNT: /* script (php script server); count number of lines */
834 if (!(poll_result = (char *) malloc(BUFSIZE))) {
835 die("ERROR: Fatal malloc error: poller.c poll_result");
836 }
837 poll_result[0] = '\0';
838
839 php_process = php_get_process();
840 sprintf(poll_result, "%d", char_count(php_cmd(reindex->arg1, php_process), '\n'));
841 if (is_debug_device(host->id)) {
842 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE SERVER COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
843 } else {
844 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE SERVER COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result));
845 }
846
847 break;
848 default:
849 SPINE_LOG(("Device[%i] HT[%i] ERROR: Unknown Assert Action!", host->id, host_thread));
850 }
851
852 if (!reindex_err) {
853 if (!(query3 = (char *)malloc(LRG_BUFSIZE))) {
854 die("ERROR: Fatal malloc error: poller.c reindex insert!");
855 }
856 query3[0] = '\0';
857
858 /* assume ok if host is up and result wasn't obtained */
859 if (poll_result == NULL || (IS_UNDEFINED(poll_result)) || (STRIMATCH(poll_result, "No Such Instance"))) {
860 if (is_debug_device(host->id) || set.spine_log_level == 2) {
861 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s=%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result));
862 }
863 assert_fail = FALSE;
864 } else if ((!strcmp(reindex->op, "=")) && (strcmp(reindex->assert_value, poll_result))) {
865 if (is_debug_device(host->id) || set.spine_log_level == 2) {
866 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s=%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result));
867 } else {
868 if (set.spine_log_level == 1) {
869 errors++;
870 }
871
872 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s=%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result));
873 }
874
875 if (host_thread == 1) {
876 snprintf(query3, LRG_BUFSIZE, "REPLACE INTO poller_command (poller_id, time, action,command) values (%i, NOW(), %i, '%i:%i')", set.poller_id, POLLER_COMMAND_REINDEX, host->id, reindex->data_query_id);
877
878 if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) {
879 db_insert(&mysqlr, REMOTE, query3);
880 } else {
881 db_insert(&mysql, LOCAL, query3);
882 }
883
884 /* set zeros */
885 memset(query3, 0, buf_length);
886 }
887 assert_fail = TRUE;
888 previous_assert_failure = TRUE;
889 } else if ((!strcmp(reindex->op, ">")) && (strtoll(reindex->assert_value, (char **)NULL, 10) < strtoll(poll_result, (char **)NULL, 10))) {
890 if (is_debug_device(host->id) || set.spine_log_level == 2) {
891 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s>%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result));
892 } else {
893 if (set.spine_log_level == 1) {
894 errors++;
895 }
896
897 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s>%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result));
898 }
899
900 if (host_thread == 1) {
901 snprintf(query3, LRG_BUFSIZE, "REPLACE INTO poller_command (poller_id, time, action, command) ValueS (%i, NOW(), %i, '%i:%i')", set.poller_id, POLLER_COMMAND_REINDEX, host->id, reindex->data_query_id);
902
903 if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) {
904 db_insert(&mysqlr, REMOTE, query3);
905 } else {
906 db_insert(&mysql, LOCAL, query3);
907 }
908
909 /* set zeros */
910 memset(query3, 0, buf_length);
911 }
912 assert_fail = TRUE;
913 previous_assert_failure = TRUE;
914 /* if uptime is set to '0' don't fail out */
915 } else if (strcmp(reindex->assert_value, "0")) {
916 if ((!strcmp(reindex->op, "<")) && (strtoll(reindex->assert_value, (char **)NULL, 10) > strtoll(poll_result, (char **)NULL, 10))) {
917 if (is_debug_device(host->id) || set.spine_log_level == 2) {
918 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s<%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result));
919 } else {
920 if (set.spine_log_level == 1) {
921 errors++;
922 }
923
924 SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s<%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result));
925 }
926
927 if (host_thread == 1) {
928 snprintf(query3, LRG_BUFSIZE, "REPLACE INTO poller_command (poller_id, time, action, command) VALUES (%i, NOW(), %i, '%i:%i')", set.poller_id, POLLER_COMMAND_REINDEX, host->id, reindex->data_query_id);
929
930 if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) {
931 db_insert(&mysqlr, REMOTE, query3);
932 } else {
933 db_insert(&mysql, LOCAL, query3);
934 }
935
936 /* set zeros */
937 memset(query3, 0, buf_length);
938 }
939 assert_fail = TRUE;
940 previous_assert_failure = TRUE;
941 }
942 }
943
944 /* update 'poller_reindex' with the correct information if:
945 * 1) the assert fails
946 * 2) the OP code is > or < meaning the current value could have changed without causing
947 * the assert to fail */
948 if ((assert_fail) || (!strcmp(reindex->op, ">")) || (!strcmp(reindex->op, "<"))) {
949 if (host_thread == 1) {
950 db_escape(&mysql, temp_poll_result, sizeof(temp_poll_result), poll_result);
951 db_escape(&mysql, temp_arg1, sizeof(temp_arg1), reindex->arg1);
952 snprintf(query3, LRG_BUFSIZE, "UPDATE poller_reindex SET assert_value='%s' WHERE host_id='%i' AND data_query_id='%i' AND arg1='%s'", temp_poll_result, host_id, reindex->data_query_id, temp_arg1);
953 db_insert(&mysql, LOCAL, query3);
954
955 /* set zeros */
956 memset(query3, 0, buf_length);
957 }
958
959 if ((assert_fail) &&
960 ((!strcmp(reindex->op, "<")) || (!strcmp(reindex->arg1,".1.3.6.1.2.1.1.3.0")))) {
961 spike_kill = TRUE;
962 if (is_debug_device(host->id) || set.spine_log_level == 2) {
963 SPINE_LOG(("Device[%i] HT[%i] NOTICE: Spike Kill in Effect for '%s'", host_id, host_thread, host->hostname));
964 } else {
965 if (set.spine_log_level == 1) {
966 errors++;
967 }
968
969 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] NOTICE: Spike Kill in Effect for '%s'", host_id, host_thread, host->hostname));
970 }
971 }
972 }
973
974 free(query3);
975
976 if (poll_result != NULL) {
977 free(poll_result);
978 }
979 }
980 }
981 }
982 } else {
983 if (is_debug_device(host->id)) {
984 SPINE_LOG(("Device[%i] HT[%i] Device has no information for recache.", host->id, host_thread));
985 } else {
986 SPINE_LOG_HIGH(("Device[%i] HT[%i] Device has no information for recache.", host->id, host_thread));
987 }
988 }
989
990 /* free the host result */
991 mysql_free_result(result);
992 } else {
993 SPINE_LOG(("Device[%i] HT[%i] ERROR: RECACHE Query Returned Null Result!", host->id, host_thread));
994 }
995
996 /* close the host snmp session, we will create again momentarily */
997 if (host->snmp_session) {
998 snmp_host_cleanup(host->snmp_session);
999 host->snmp_session = NULL;
1000 }
1001 }
1002
1003 /* calculate the number of poller items to poll this cycle */
1004 num_rows = 0;
1005 if (set.poller_interval == 0) {
1006 /* get the number of agents */
1007 if ((result = db_query(&mysql, LOCAL, query9)) != 0) {
1008 num_snmp_agents = mysql_num_rows(result);
1009 mysql_free_result(result);
1010
1011 /* get the poller items */
1012 if ((result = db_query(&mysql, LOCAL, query1)) != 0) {
1013 num_rows = mysql_num_rows(result);
1014 } else {
1015 SPINE_LOG(("Device[%i] HT[%i] ERROR: Unable to Retrieve Rows due to Null Result!", host->id, host_thread));
1016 }
1017 } else {
1018 SPINE_LOG(("Device[%i] HT[%i] ERROR: Agent Count Query Returned Null Result!", host->id, host_thread));
1019 }
1020 } else {
1021 /* get the number of agents */
1022 if ((result = db_query(&mysql, LOCAL, query10)) != 0) {
1023 num_snmp_agents = (int)mysql_num_rows(result);
1024 mysql_free_result(result);
1025
1026 /* get the poller items */
1027 if ((result = db_query(&mysql, LOCAL, query5)) != 0) {
1028 num_rows = mysql_num_rows(result);
1029 } else {
1030 SPINE_LOG(("Device[%i] HT[%i] ERROR: Unable to Retrieve Rows due to Null Result!", host->id, host_thread));
1031 }
1032 } else {
1033 SPINE_LOG(("Device[%i] HT[%i] ERROR: Agent Count Query Returned Null Result!", host->id, host_thread));
1034 }
1035 }
1036
1037 if (num_rows > 0) {
1038 /* retreive each hosts polling items from poller cache and load into array */
1039 poller_items = (target_t *) calloc(num_rows, sizeof(target_t));
1040
1041 i = 0;
1042 while ((row = mysql_fetch_row(result))) {
1043 /* initialize monitored object */
1044 poller_items[i].target_id = 0;
1045 poller_items[i].action = -1;
1046 poller_items[i].hostname[0] = '\0';
1047 poller_items[i].snmp_community[0] = '\0';
1048 poller_items[i].snmp_version = 1;
1049 poller_items[i].snmp_username[0] = '\0';
1050 poller_items[i].snmp_password[0] = '\0';
1051 poller_items[i].snmp_auth_protocol[0] = '\0';
1052 poller_items[i].snmp_priv_passphrase[0] = '\0';
1053 poller_items[i].snmp_priv_protocol[0] = '\0';
1054 poller_items[i].snmp_context[0] = '\0';
1055 poller_items[i].snmp_engine_id[0] = '\0';
1056 poller_items[i].snmp_port = 161;
1057 poller_items[i].snmp_timeout = 500;
1058 poller_items[i].rrd_name[0] = '\0';
1059 poller_items[i].rrd_path[0] = '\0';
1060 poller_items[i].arg1[0] = '\0';
1061 poller_items[i].arg2[0] = '\0';
1062 poller_items[i].arg3[0] = '\0';
1063 poller_items[i].local_data_id = 0;
1064 poller_items[i].rrd_num = 0;
1065
1066 if (row[0] != NULL) poller_items[i].action = atoi(row[0]);
1067
1068 if (row[1] != NULL) snprintf(poller_items[i].hostname, sizeof(poller_items[i].hostname), "%s", row[1]);
1069 if (row[2] != NULL) snprintf(poller_items[i].snmp_community, sizeof(poller_items[i].snmp_community), "%s", row[2]);
1070
1071 if (row[3] != NULL) poller_items[i].snmp_version = atoi(row[3]);
1072
1073 if (row[4] != NULL) snprintf(poller_items[i].snmp_username, sizeof(poller_items[i].snmp_username), "%s", row[4]);
1074 if (row[5] != NULL) snprintf(poller_items[i].snmp_password, sizeof(poller_items[i].snmp_password), "%s", row[5]);
1075
1076 if (row[6] != NULL) snprintf(poller_items[i].rrd_name, sizeof(poller_items[i].rrd_name), "%s", row[6]);
1077 if (row[7] != NULL) snprintf(poller_items[i].rrd_path, sizeof(poller_items[i].rrd_path), "%s", row[7]);
1078 if (row[8] != NULL) snprintf(poller_items[i].arg1, sizeof(poller_items[i].arg1), "%s", row[8]);
1079 if (row[9] != NULL) snprintf(poller_items[i].arg2, sizeof(poller_items[i].arg2), "%s", row[9]);
1080 if (row[10] != NULL) snprintf(poller_items[i].arg3, sizeof(poller_items[i].arg3), "%s", row[10]);
1081
1082 if (row[11] != NULL) poller_items[i].local_data_id = atoi(row[11]);
1083
1084 if (row[12] != NULL) poller_items[i].rrd_num = atoi(row[12]);
1085 if (row[13] != NULL) poller_items[i].snmp_port = atoi(row[13]);
1086 if (row[14] != NULL) poller_items[i].snmp_timeout = atoi(row[14]);
1087
1088 if (row[15] != NULL) snprintf(poller_items[i].snmp_auth_protocol,
1089 sizeof(poller_items[i].snmp_auth_protocol), "%s", row[15]);
1090 if (row[16] != NULL) snprintf(poller_items[i].snmp_priv_passphrase,
1091 sizeof(poller_items[i].snmp_priv_passphrase), "%s", row[16]);
1092 if (row[17] != NULL) snprintf(poller_items[i].snmp_priv_protocol,
1093 sizeof(poller_items[i].snmp_priv_protocol), "%s", row[17]);
1094 if (row[18] != NULL) snprintf(poller_items[i].snmp_context,
1095 sizeof(poller_items[i].snmp_context), "%s", row[18]);
1096 if (row[19] != NULL) snprintf(poller_items[i].snmp_engine_id,
1097 sizeof(poller_items[i].snmp_engine_id), "%s", row[19]);
1098
1099 SET_UNDEFINED(poller_items[i].result);
1100
1101 if (poller_items[i].action == POLLER_ACTION_SNMP) {
1102 snmp_poller_items++;
1103 }
1104
1105 i++;
1106 }
1107
1108 /* free the mysql result */
1109 mysql_free_result(result);
1110
1111 /* create an array for snmp oids */
1112 snmp_oids = (snmp_oids_t *) calloc(host->max_oids, sizeof(snmp_oids_t));
1113
1114 /* initialize all the memory to insure we don't get issues */
1115 memset(snmp_oids, 0, sizeof(snmp_oids_t)*host->max_oids);
1116
1117 /* log an informative message */
1118 if (is_debug_device(host_id)) {
1119 SPINE_LOG(("Device[%i] HT[%i] NOTE: There are '%i' Polling Items for this Device", host_id, host_thread, num_rows));
1120 } else {
1121 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] NOTE: There are '%i' Polling Items for this Device", host_id, host_thread, num_rows));
1122 }
1123
1124 i = 0; k = 0;
1125 while ((i < num_rows) && (!host->ignore_host)) {
1126 thread_start = get_time_as_double();
1127
1128 switch(poller_items[i].action) {
1129 case POLLER_ACTION_SNMP: /* raw SNMP poll */
1130 /* initialize or reinitialize snmp as required */
1131 if (k == 0) {
1132 last_snmp_port = poller_items[i].snmp_port;
1133 last_snmp_version = poller_items[i].snmp_version;
1134
1135 STRNCOPY(last_snmp_community, poller_items[i].snmp_community);
1136 STRNCOPY(last_snmp_username, poller_items[i].snmp_username);
1137 STRNCOPY(last_snmp_password, poller_items[i].snmp_password);
1138 STRNCOPY(last_snmp_auth_protocol, poller_items[i].snmp_auth_protocol);
1139 STRNCOPY(last_snmp_priv_passphrase, poller_items[i].snmp_priv_passphrase);
1140 STRNCOPY(last_snmp_priv_protocol, poller_items[i].snmp_priv_protocol);
1141 STRNCOPY(last_snmp_context, poller_items[i].snmp_context);
1142 STRNCOPY(last_snmp_engine_id, poller_items[i].snmp_engine_id);
1143
1144 host->snmp_session = snmp_host_init(host->id, poller_items[i].hostname,
1145 poller_items[i].snmp_version, poller_items[i].snmp_community,
1146 poller_items[i].snmp_username, poller_items[i].snmp_password,
1147 poller_items[i].snmp_auth_protocol, poller_items[i].snmp_priv_passphrase,
1148 poller_items[i].snmp_priv_protocol, poller_items[i].snmp_context,
1149 poller_items[i].snmp_engine_id,
1150 poller_items[i].snmp_port, poller_items[i].snmp_timeout);
1151
1152 k++;
1153 }
1154
1155 /* catch snmp initialization issues */
1156 if (!host->snmp_session) {
1157 host->ignore_host = TRUE;
1158 break;
1159 }
1160
1161 /* some snmp data changed from poller item to poller item. therefore, poll host and store data */
1162 if ((last_snmp_port != poller_items[i].snmp_port) ||
1163 (last_snmp_version != poller_items[i].snmp_version) ||
1164 (poller_items[i].snmp_version < 3 &&
1165 (!STRMATCH(last_snmp_community, poller_items[i].snmp_community))) ||
1166 (poller_items[i].snmp_version > 2 &&
1167 ((!STRMATCH(last_snmp_username, poller_items[i].snmp_username)) ||
1168 (!STRMATCH(last_snmp_password, poller_items[i].snmp_password)) ||
1169 (!STRMATCH(last_snmp_auth_protocol, poller_items[i].snmp_auth_protocol)) ||
1170 (!STRMATCH(last_snmp_priv_passphrase, poller_items[i].snmp_priv_passphrase)) ||
1171 (!STRMATCH(last_snmp_priv_protocol, poller_items[i].snmp_priv_protocol)) ||
1172 (!STRMATCH(last_snmp_context, poller_items[i].snmp_context)) ||
1173 (!STRMATCH(last_snmp_engine_id, poller_items[i].snmp_engine_id))))) {
1174
1175 if (num_oids > 0) {
1176 snmp_get_multi(host, poller_items, snmp_oids, num_oids);
1177
1178 for (j = 0; j < num_oids; j++) {
1179 if (host->ignore_host) {
1180 SPINE_LOG(("Device[%i] HT[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname));
1181 SET_UNDEFINED(snmp_oids[j].result);
1182 } else if (IS_UNDEFINED(snmp_oids[j].result)) {
1183 if (set.spine_log_level == 2) {
1184 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1185 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id,
1186 host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1187 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1188 } else if (set.spine_log_level == 1) {
1189 errors++;
1190 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1191 }
1192
1193 /* continue */
1194 } else if ((is_numeric(snmp_oids[j].result)) || (is_multipart_output(snmp_oids[j].result))) {
1195 /* continue */
1196 } else if (is_hexadecimal(snmp_oids[j].result, TRUE)) {
1197 snprintf(snmp_oids[j].result, RESULTS_BUFFER, "%lld", hex2dec(snmp_oids[j].result));
1198 } else if ((STRIMATCH(snmp_oids[j].result, "U")) ||
1199 (STRIMATCH(snmp_oids[j].result, "Nan"))) {
1200 if (set.spine_log_level == 2) {
1201 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1202 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id,
1203 host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1204 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1205 } else if (set.spine_log_level == 1) {
1206 errors++;
1207 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1208 }
1209
1210 /* is valid output, continue */
1211 } else {
1212 /* remove double or single quotes from string */
1213 snprintf(temp_result, RESULTS_BUFFER, "%s", strip_alpha(trim(snmp_oids[j].result)));
1214 snprintf(snmp_oids[j].result , RESULTS_BUFFER, "%s", temp_result);
1215
1216 /* detect erroneous non-numeric result */
1217 if (!validate_result(snmp_oids[j].result)) {
1218 if (set.spine_log_level == 2) {
1219 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1220 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id,
1221 host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1222 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1223 } else if (set.spine_log_level == 1) {
1224 errors++;
1225 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1226 }
1227
1228 SET_UNDEFINED(snmp_oids[j].result);
1229 }
1230 }
1231
1232 snprintf(poller_items[snmp_oids[j].array_position].result, RESULTS_BUFFER, "%s", snmp_oids[j].result);
1233
1234 thread_end = get_time_as_double();
1235
1236 if (is_debug_device(host_id)) {
1237 SPINE_LOG(("Device[%i] HT[%i] DS[%i] TT[%.2f] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, (thread_end - thread_start) * 1000, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result));
1238 } else {
1239 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] TT[%.2f] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, (thread_end - thread_start) * 1000, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result));
1240 }
1241 }
1242
1243 /* reset num_snmps */
1244 num_oids = 0;
1245
1246 /* initialize all the memory to insure we don't get issues */
1247 memset(snmp_oids, 0, sizeof(snmp_oids_t)*host->max_oids);
1248 }
1249
1250 snmp_host_cleanup(host->snmp_session);
1251 host->snmp_session = snmp_host_init(host->id, poller_items[i].hostname,
1252 poller_items[i].snmp_version, poller_items[i].snmp_community,
1253 poller_items[i].snmp_username, poller_items[i].snmp_password,
1254 poller_items[i].snmp_auth_protocol, poller_items[i].snmp_priv_passphrase,
1255 poller_items[i].snmp_priv_protocol, poller_items[i].snmp_context,
1256 poller_items[i].snmp_engine_id,
1257 poller_items[i].snmp_port, poller_items[i].snmp_timeout);
1258
1259 last_snmp_port = poller_items[i].snmp_port;
1260 last_snmp_version = poller_items[i].snmp_version;
1261
1262 STRNCOPY(last_snmp_community, poller_items[i].snmp_community);
1263 STRNCOPY(last_snmp_username, poller_items[i].snmp_username);
1264 STRNCOPY(last_snmp_password, poller_items[i].snmp_password);
1265 STRNCOPY(last_snmp_auth_protocol, poller_items[i].snmp_auth_protocol);
1266 STRNCOPY(last_snmp_priv_passphrase, poller_items[i].snmp_priv_passphrase);
1267 STRNCOPY(last_snmp_priv_protocol, poller_items[i].snmp_priv_protocol);
1268 STRNCOPY(last_snmp_context, poller_items[i].snmp_context);
1269 STRNCOPY(last_snmp_engine_id, poller_items[i].snmp_engine_id);
1270 }
1271
1272 if (num_oids >= host->max_oids) {
1273 snmp_get_multi(host, poller_items, snmp_oids, num_oids);
1274
1275 for (j = 0; j < num_oids; j++) {
1276 if (host->ignore_host) {
1277 SPINE_LOG(("Device[%i] HT[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname));
1278 SET_UNDEFINED(snmp_oids[j].result);
1279 } else if (IS_UNDEFINED(snmp_oids[j].result)) {
1280 if (set.spine_log_level == 2) {
1281 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1282 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id,
1283 host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1284 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1285 } else if (set.spine_log_level == 1) {
1286 errors++;
1287 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1288 }
1289
1290 /* continue */
1291 } else if ((is_numeric(snmp_oids[j].result)) || (is_multipart_output(snmp_oids[j].result))) {
1292 /* continue */
1293 } else if (is_hexadecimal(snmp_oids[j].result, TRUE)) {
1294 snprintf(snmp_oids[j].result, RESULTS_BUFFER, "%lld", hex2dec(snmp_oids[j].result));
1295 } else if ((STRIMATCH(snmp_oids[j].result, "U")) ||
1296 (STRIMATCH(snmp_oids[j].result, "Nan"))) {
1297 if (set.spine_log_level == 2) {
1298 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1299 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id,
1300 host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1301 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1302 } else if (set.spine_log_level == 1) {
1303 errors++;
1304 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1305 }
1306
1307 /* is valid output, continue */
1308 } else {
1309 /* remove double or single quotes from string */
1310 snprintf(temp_result, RESULTS_BUFFER, "%s", snmp_oids[j].result);
1311 snprintf(snmp_oids[j].result , RESULTS_BUFFER, "%s", temp_result);
1312
1313 /* detect erroneous non-numeric result */
1314 if (!validate_result(snmp_oids[j].result)) {
1315 if (set.spine_log_level == 2) {
1316 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1317 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id,
1318 host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1319 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1320 } else if (set.spine_log_level == 1) {
1321 errors++;
1322 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1323 }
1324
1325 SET_UNDEFINED(snmp_oids[j].result);
1326 }
1327 }
1328
1329 snprintf(poller_items[snmp_oids[j].array_position].result, RESULTS_BUFFER, "%s", snmp_oids[j].result);
1330
1331 thread_end = get_time_as_double();
1332
1333 if (is_debug_device(host_id)) {
1334 SPINE_LOG(("Device[%i] HT[%i] DS[%i] TT[%.2f] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, (thread_end - thread_start) * 1000, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result));
1335 } else {
1336 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] TT[%.2f] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, (thread_end - thread_start) * 1000, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result));
1337 }
1338
1339 if (!IS_UNDEFINED(poller_items[snmp_oids[j].array_position].result)) {
1340 /* insert a NaN in place of the actual value if the snmp agent restarts */
1341 if ((spike_kill) && (!strstr(poller_items[snmp_oids[j].array_position].result,":"))) {
1342 SET_UNDEFINED(poller_items[snmp_oids[j].array_position].result);
1343 }
1344 }
1345 }
1346
1347 /* reset num_snmps */
1348 num_oids = 0;
1349
1350 /* initialize all the memory to insure we don't get issues */
1351 memset(snmp_oids, 0, sizeof(snmp_oids_t)*host->max_oids);
1352 }
1353
1354 snprintf(snmp_oids[num_oids].oid, sizeof(snmp_oids[num_oids].oid), "%s", poller_items[i].arg1);
1355 snmp_oids[num_oids].array_position = i;
1356 num_oids++;
1357
1358 break;
1359 case POLLER_ACTION_SCRIPT: /* execute script file */
1360 poll_result = exec_poll(host, poller_items[i].arg1, poller_items[i].local_data_id, "DS");
1361
1362 /* process the result */
1363 if (IS_UNDEFINED(poll_result)) {
1364 SET_UNDEFINED(poller_items[i].result);
1365 if (set.spine_log_level == 2) {
1366 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s",
1367 host_id, host_thread, poller_items[i].local_data_id,
1368 poller_items[i].arg1, poller_items[i].result));
1369 } else if (set.spine_log_level == 1) {
1370 errors++;
1371 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[i].local_data_id, false);
1372 }
1373 } else if ((is_numeric(poll_result)) || (is_multipart_output(trim(poll_result)))) {
1374 snprintf(poller_items[i].result, RESULTS_BUFFER, "%s", poll_result);
1375 } else if (is_hexadecimal(poll_result, TRUE)) {
1376 snprintf(poller_items[i].result, RESULTS_BUFFER, "%lld", hex2dec(poll_result));
1377 } else {
1378 /* remove double or single quotes from string */
1379 snprintf(temp_result, RESULTS_BUFFER, "%s", strip_alpha(trim(poll_result)));
1380 snprintf(poller_items[i].result , RESULTS_BUFFER, "%s", temp_result);
1381
1382 /* detect erroneous result. can be non-numeric */
1383 if (!validate_result(poller_items[i].result)) {
1384 if (set.spine_log_level == 2) {
1385 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s",
1386 host_id, host_thread, poller_items[i].local_data_id,
1387 poller_items[i].arg1, poller_items[i].result));
1388 } else if (set.spine_log_level == 1) {
1389 errors++;
1390 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[i].local_data_id, false);
1391 }
1392
1393 SET_UNDEFINED(poller_items[i].result);
1394 }
1395 }
1396
1397 if (poll_result) free(poll_result);
1398
1399 thread_end = get_time_as_double();
1400
1401 if (is_debug_device(host_id)) {
1402 SPINE_LOG(("Device[%i] HT[%i] DS[%i] TT[%.2f] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, (thread_end - thread_start) * 1000, poller_items[i].arg1, poller_items[i].result));
1403 } else {
1404 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] TT[%.2f] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, (thread_end - thread_start) * 1000, poller_items[i].arg1, poller_items[i].result));
1405 }
1406
1407 if (!IS_UNDEFINED(poller_items[i].result)) {
1408 /* insert a NaN in place of the actual value if the snmp agent restarts */
1409 if ((spike_kill) && (!strstr(poller_items[i].result,":"))) {
1410 SET_UNDEFINED(poller_items[i].result);
1411 }
1412 }
1413
1414 break;
1415 case POLLER_ACTION_PHP_SCRIPT_SERVER: /* execute script server */
1416 php_process = php_get_process();
1417
1418 poll_result = php_cmd(poller_items[i].arg1, php_process);
1419
1420 /* process the output */
1421 if (IS_UNDEFINED(poll_result)) {
1422 SET_UNDEFINED(poller_items[i].result);
1423 if (set.spine_log_level == 2) {
1424 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s",
1425 host_id, host_thread, poller_items[i].local_data_id,
1426 poller_items[i].arg1, poller_items[i].result));
1427 } else if (set.spine_log_level == 1) {
1428 errors++;
1429 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[i].local_data_id, false);
1430 }
1431 } else if ((is_numeric(poll_result)) || (is_multipart_output(trim(poll_result)))) {
1432 snprintf(poller_items[i].result, RESULTS_BUFFER, "%s", poll_result);
1433 } else if (is_hexadecimal(poll_result, TRUE)) {
1434 snprintf(poller_items[i].result, RESULTS_BUFFER, "%lld", hex2dec(poll_result));
1435 } else {
1436 /* remove double or single quotes from string */
1437 snprintf(temp_result, RESULTS_BUFFER, "%s", strip_alpha(trim(poll_result)));
1438 snprintf(poller_items[i].result , RESULTS_BUFFER, "%s", temp_result);
1439
1440 /* detect erroneous result. can be non-numeric */
1441 if (!validate_result(poller_items[i].result)) {
1442 if (set.spine_log_level == 2) {
1443 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s",
1444 host_id, host_thread, poller_items[i].local_data_id,
1445 poller_items[i].arg1, poller_items[i].result));
1446 } else if (set.spine_log_level == 1) {
1447 errors++;
1448 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[i].local_data_id, false);
1449 }
1450
1451 SET_UNDEFINED(poller_items[i].result);
1452 }
1453 }
1454
1455 if (poll_result) free(poll_result);
1456
1457 thread_end = get_time_as_double();
1458
1459 if (is_debug_device(host_id)) {
1460 SPINE_LOG(("Device[%i] HT[%i] DS[%i] TT[%.2f] SS[%i] SERVER: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, (thread_end - thread_start) * 1000, php_process, poller_items[i].arg1, poller_items[i].result));
1461 } else {
1462 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] TT[%.2f] SS[%i] SERVER: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, (thread_end - thread_start) * 1000, php_process, poller_items[i].arg1, poller_items[i].result));
1463 }
1464
1465 if (IS_UNDEFINED(poller_items[i].result)) {
1466 /* insert a NaN in place of the actual value if the snmp agent restarts */
1467 if ((spike_kill) && (!STRIMATCH(poller_items[i].result,":"))) {
1468 SET_UNDEFINED(poller_items[i].result);
1469 }
1470 }
1471
1472 break;
1473 default: /* unknown action, generate error */
1474 SPINE_LOG(("Device[%i] HT[%i] DS[%i] ERROR: Unknown Poller Action: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1));
1475
1476 break;
1477 }
1478
1479 i++;
1480 rows_processed++;
1481 }
1482
1483 /* process last multi-get request if applicable */
1484 if (num_oids > 0) {
1485 snmp_get_multi(host, poller_items, snmp_oids, num_oids);
1486
1487 for (j = 0; j < num_oids; j++) {
1488 if (host->ignore_host) {
1489 SPINE_LOG(("Device[%i] HT[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname));
1490 SET_UNDEFINED(snmp_oids[j].result);
1491 } else if (IS_UNDEFINED(snmp_oids[j].result)) {
1492 if (set.spine_log_level == 2) {
1493 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1494 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version,
1495 host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1496 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1497 } else if (set.spine_log_level == 1) {
1498 errors++;
1499 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1500 }
1501
1502 /* continue */
1503 } else if ((is_numeric(snmp_oids[j].result)) || (is_multipart_output(snmp_oids[j].result))) {
1504 /* continue */
1505 } else if (is_hexadecimal(snmp_oids[j].result, TRUE)) {
1506 snprintf(snmp_oids[j].result, RESULTS_BUFFER, "%lld", hex2dec(snmp_oids[j].result));
1507 } else if ((STRIMATCH(snmp_oids[j].result, "U")) ||
1508 (STRIMATCH(snmp_oids[j].result, "Nan"))) {
1509 if (set.spine_log_level == 2) {
1510 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1511 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version,
1512 host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1513 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1514 } else if (set.spine_log_level == 1) {
1515 errors++;
1516 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1517 }
1518
1519 /* is valid output, continue */
1520 } else {
1521 /* remove double or single quotes from string */
1522 snprintf(temp_result, RESULTS_BUFFER, "%s", strip_alpha(trim(snmp_oids[j].result)));
1523 snprintf(snmp_oids[j].result , RESULTS_BUFFER, "%s", temp_result);
1524
1525 /* detect erroneous non-numeric result */
1526 if (!validate_result(snmp_oids[j].result)) {
1527 if (set.spine_log_level == 2) {
1528 SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s",
1529 host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version,
1530 host->hostname, poller_items[snmp_oids[j].array_position].rrd_name,
1531 poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result));
1532 } else if (set.spine_log_level == 1) {
1533 errors++;
1534 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, false);
1535 }
1536
1537 SET_UNDEFINED(snmp_oids[j].result);
1538 }
1539 }
1540
1541 snprintf(poller_items[snmp_oids[j].array_position].result, RESULTS_BUFFER, "%s", snmp_oids[j].result);
1542
1543 thread_end = get_time_as_double();
1544
1545 if (is_debug_device(host_id)) {
1546 SPINE_LOG(("Device[%i] HT[%i] DS[%i] TT[%.2f] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, (thread_end - thread_start) * 1000, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result));
1547 } else {
1548 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] TT[%.2f] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, (thread_end - thread_start) * 1000, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result));
1549 }
1550
1551 if (!IS_UNDEFINED(poller_items[snmp_oids[j].array_position].result)) {
1552 /* insert a NaN in place of the actual value if the snmp agent restarts */
1553 if ((spike_kill) && (!strstr(poller_items[snmp_oids[j].array_position].result,":"))) {
1554 SET_UNDEFINED(poller_items[snmp_oids[j].array_position].result);
1555 }
1556 }
1557 }
1558 }
1559
1560 buf_length = MAX_MYSQL_BUF_SIZE+RESULTS_BUFFER;
1561
1562 /* insert the query results into the database */
1563 if (!(query3 = (char *)malloc(buf_length))) {
1564 die("ERROR: Fatal malloc error: poller.c query3 output buffer!");
1565 }
1566
1567 /* set zeros */
1568 memset(query3, 0, buf_length);
1569
1570 /* append data */
1571 strncat(query3, query8, query8_len);
1572
1573 out_buffer = strlen(query3);
1574
1575 if (set.boost_redirect && set.boost_enabled) {
1576 /* insert the query results into the database */
1577 if (!(query12 = (char *)malloc(buf_length))) {
1578 die("ERROR: Fatal malloc error: poller.c query12 boost output buffer!");
1579 }
1580
1581 /* set zeros */
1582 memset(query12, 0, buf_length);
1583
1584 /* append data */
1585 strncat(query12, query11, query11_len);
1586 }
1587
1588 int mode;
1589 if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) {
1590 SPINE_LOG_DEBUG(("DEBUG: Setting up writes to remote database"));
1591 mysqlt = mysqlr;
1592 mode = REMOTE;
1593 } else {
1594 SPINE_LOG_DEBUG(("DEBUG: Setting up writes to local database"));
1595 mysqlt = mysql;
1596 mode = LOCAL;
1597 }
1598
1599 i = 0;
1600 while (i < rows_processed) {
1601 snprintf(result_string, RESULTS_BUFFER+SMALL_BUFSIZE, " (%i,'%s',FROM_UNIXTIME(%s),'%s')",
1602 poller_items[i].local_data_id,
1603 poller_items[i].rrd_name,
1604 host_time,
1605 poller_items[i].result);
1606
1607 result_length = strlen(result_string);
1608
1609 /* if the next element to the buffer will overflow it, write to the database */
1610 if ((out_buffer + result_length) >= MAX_MYSQL_BUF_SIZE) {
1611 /* append the suffix */
1612 strncat(query3, posuffix, posuffix_len);
1613
1614 /* insert the record */
1615 db_insert(&mysqlt, mode, query3);
1616
1617 /* re-initialize the query buffer */
1618 memset(query3, 0, MAX_MYSQL_BUF_SIZE+RESULTS_BUFFER);
1619
1620 strncat(query3, query8, query8_len);
1621
1622 /* insert the record for boost */
1623 if (set.boost_redirect && set.boost_enabled) {
1624 /* append the suffix */
1625 strncat(query12, posuffix, posuffix_len);
1626
1627 db_insert(&mysqlt, mode, query12);
1628
1629 memset(query12, 0, MAX_MYSQL_BUF_SIZE+RESULTS_BUFFER);
1630
1631 strncat(query12, query11, query11_len);
1632 }
1633
1634 /* reset the output buffer length */
1635 out_buffer = strlen(query3);
1636
1637 /* set binary, let the system know we are a new buffer */
1638 new_buffer = TRUE;
1639 }
1640
1641 /* if this is our first pass, or we just outputted to the database, need to change the delimeter */
1642 if (new_buffer) {
1643 result_string[0] = ' ';
1644 } else {
1645 result_string[0] = ',';
1646 }
1647
1648 strncat(query3, result_string, result_length);
1649
1650 if (set.boost_redirect && set.boost_enabled) {
1651 strncat(query12, result_string, result_length);
1652 }
1653
1654 out_buffer = out_buffer + strlen(result_string);
1655 new_buffer = FALSE;
1656 i++;
1657 }
1658
1659 /* perform the last insert if there is data to process */
1660 if (out_buffer > strlen(query8)) {
1661 /* append the suffix */
1662 strncat(query3, posuffix, posuffix_len);
1663
1664 /* insert records into database */
1665 db_insert(&mysqlt, mode, query3);
1666
1667 /* insert the record for boost */
1668 if (set.boost_redirect && set.boost_enabled) {
1669 /* append the suffix */
1670 strncat(query12, posuffix, posuffix_len);
1671
1672 db_insert(&mysqlt, mode, query12);
1673 }
1674 }
1675
1676 /* cleanup memory and prepare for function exit */
1677 if (host->snmp_session) {
1678 snmp_host_cleanup(host->snmp_session);
1679 }
1680
1681 free(query3);
1682 if (set.boost_redirect && set.boost_enabled) {
1683 free(query12);
1684 }
1685
1686 free(poller_items);
1687 free(snmp_oids);
1688 } else {
1689 /* free the mysql result */
1690 mysql_free_result(result);
1691 }
1692
1693 free(host);
1694 free(reindex);
1695 free(ping);
1696
1697 /* update poller_items table for next polling interval */
1698 if (host_thread == last_host_thread) {
1699 db_query(&mysql, LOCAL, query6);
1700 }
1701
1702 /* record the polling time for the device */
1703 poll_time = get_time_as_double() - poll_time;
1704 if (is_debug_device(host_id)) {
1705 SPINE_LOG(("Device[%i] HT[%i] Total Time: %0.2g Seconds", host_id, host_thread, poll_time));
1706 } else {
1707 SPINE_LOG_MEDIUM(("Device[%i] HT[%i] Total Time: %0.2g Seconds", host_id, host_thread, poll_time));
1708 }
1709
1710 /* record the total time for the host */
1711 poll_time = get_time_as_double();
1712 query1[0] = '\0';
1713 snprintf(query1, BUFSIZE, "UPDATE host SET polling_time=%.3f - %.3f WHERE id=%i", poll_time, host_time_double, host_id);
1714 db_query(&mysql, LOCAL, query1);
1715
1716 db_release_connection(LOCAL, local_cnn->id);
1717
1718 if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) {
1719 db_release_connection(REMOTE, remote_cnn->id);
1720 }
1721
1722 #ifndef OLD_MYSQL
1723 mysql_thread_end();
1724 #endif
1725
1726 if (is_debug_device(host_id)) {
1727 SPINE_LOG(("DEBUG: Device[%i] HT[%i] DEBUG: HOST COMPLETE: About to Exit Device Polling Thread Function", host_id, host_thread));
1728 } else {
1729 SPINE_LOG_DEBUG(("DEBUG: Device[%i] HT[%i] DEBUG: HOST COMPLETE: About to Exit Device Polling Thread Function", host_id, host_thread));
1730 }
1731
1732 buffer_output_errors(error_string, buf_size, buf_errors, host_id, host_thread, 0, true);
1733
1734 free(error_string);
1735 free(buf_size);
1736 free(buf_errors);
1737
1738 *host_errors = errors;
1739 }
1740
1741 /*! \fn void buffer_output_errors(local_data_id) {
1742 * \brief buffers output errors and pushes those errors to standard
1743 * output as required.
1744 * \param char* buffer - pointer to the output buffer
1745 * \param int device_id - the device id
1746 * \param int thread id - the device thread
1747 * \param int local_data_id - the local data id
1748 * \param boolean flush - flush any part of buffer
1749 */
buffer_output_errors(char * error_string,int * buf_size,int * buf_errors,int device_id,int thread_id,int local_data_id,bool flush)1750 void buffer_output_errors(char *error_string, int *buf_size, int *buf_errors, int device_id, int thread_id, int local_data_id, bool flush) {
1751 int error_len;
1752 char tbuffer[SMALL_BUFSIZE];
1753
1754 if (flush && *buf_errors > 0) {
1755 SPINE_LOG(("WARNING: Invalid Response(s), Errors[%i] Device[%i] Thread[%i] DS[%s]", *buf_errors, device_id, thread_id, error_string));
1756 } else if (!flush) {
1757 snprintf(tbuffer, SMALL_BUFSIZE, *buf_errors > 0 ? ", %i" : "%i", local_data_id);
1758 error_len = strlen(tbuffer);
1759 if (*buf_size + error_len >= DBL_BUFSIZE) {
1760 SPINE_LOG(("WARNING: Invalid Response(s), Errors[%i] Device[%i] Thread[%i] DS[%s]", *buf_errors, device_id, thread_id, error_string));
1761 *buf_errors = 1;
1762 *buf_size = snprintf(error_string, DBL_BUFSIZE, "%i", local_data_id);
1763 } else {
1764 (*buf_errors)++;
1765 snprintf(error_string + *buf_size, DBL_BUFSIZE, "%s", tbuffer);
1766 *buf_size += error_len;
1767 }
1768 }
1769 }
1770
1771 /*! \fn int is_multipart_output(char *result)
1772 * \brief validates the output syntax is a valid name value pair syntax
1773 * \param result the value to be checked for legality
1774 *
1775 * This function will poll a specific host using the script pointed to by
1776 * the command variable.
1777 *
1778 * \return TRUE if the result is valid, otherwise FALSE.
1779 *
1780 */
is_multipart_output(char * result)1781 int is_multipart_output(char *result) {
1782 int space_cnt = 0;
1783 int delim_cnt = 0;
1784 int i;
1785
1786 /* check the easy cases first */
1787 if (result) {
1788 /* it must have delimiters */
1789 if ((strstr(result, ":")) || (strstr(result, "!"))) {
1790 if (!strstr(result, " ")) {
1791 return TRUE;
1792 } else {
1793 const int len = strlen(result);
1794
1795 for (i=0; i<len; i++) {
1796 if ((result[i] == ':') || (result[i] == '!')) {
1797 delim_cnt = delim_cnt + 1;
1798 } else if (result[i] == ' ') {
1799 space_cnt = space_cnt + 1;
1800 }
1801 }
1802
1803 if (space_cnt+1 == delim_cnt) {
1804 return TRUE;
1805 } else {
1806 return FALSE;
1807 }
1808 }
1809 }
1810 }
1811
1812 return FALSE;
1813 }
1814
get_system_information(host_t * host,MYSQL * mysql,int system)1815 void get_system_information(host_t *host, MYSQL *mysql, int system) {
1816 char *poll_result;
1817
1818 SPINE_LOG_MEDIUM(("Device[%d] Checking for System Information Update", host->id));
1819
1820 if (set.mibs || system) {
1821 if (is_debug_device(host->id)) {
1822 SPINE_LOG(("Device[%d] Updating Full System Information Table", host->id));
1823 } else {
1824 SPINE_LOG_MEDIUM(("Device[%d] Updating Full System Information Table", host->id));
1825 }
1826
1827 SPINE_LOG_DEVDBG(("DEVDBG: Device[%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.1.0');", host->id));
1828 poll_result = snmp_get(host, ".1.3.6.1.2.1.1.1.0");
1829 SPINE_LOG_DEVDBG(("DEVDBG: Device[%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.1.0'); [complete]", host->id));
1830
1831 if (poll_result) {
1832 db_escape(mysql, host->snmp_sysDescr, sizeof(host->snmp_sysDescr), poll_result);
1833 free(poll_result);
1834 }
1835
1836 SPINE_LOG_DEVDBG(("DEVDBG: Device[%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.2.0');", host->id));
1837 poll_result = snmp_get(host, ".1.3.6.1.2.1.1.2.0");
1838 SPINE_LOG_DEVDBG(("DEVDBG: Device[%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.2.0'); [complete]", host->id));
1839
1840 if (poll_result) {
1841 db_escape(mysql, host->snmp_sysObjectID, sizeof(host->snmp_sysObjectID), poll_result);
1842 free(poll_result);
1843 }
1844
1845 SPINE_LOG_DEVDBG(("DEVDBG: Device[%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.3.0');", host->id));
1846 poll_result = snmp_get(host, ".1.3.6.1.2.1.1.3.0");
1847 SPINE_LOG_DEVDBG(("DEVDGB: Device[%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.3.0'); [complete]", host->id));
1848
1849 if (poll_result) {
1850 host->snmp_sysUpTimeInstance = atoi(poll_result);
1851 free(poll_result);
1852 }
1853
1854 SPINE_LOG_DEVDBG(("DEVDBG: Device [%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.4.0');", host->id));
1855 poll_result = snmp_get(host, ".1.3.6.1.2.1.1.4.0");
1856 SPINE_LOG_DEVDBG(("DEVDBG: Device [%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.4.0'); [complete]", host->id));
1857
1858 if (poll_result) {
1859 db_escape(mysql, host->snmp_sysContact, sizeof(host->snmp_sysContact), poll_result);
1860 free(poll_result);
1861 }
1862
1863 SPINE_LOG_DEVDBG(("DEVDBG: Device [%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.5.0');", host->id));
1864 poll_result = snmp_get(host, ".1.3.6.1.2.1.1.5.0");
1865 SPINE_LOG_DEVDBG(("DEVDBG: Device [%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.5.0'); [complete]", host->id));
1866
1867 if (poll_result) {
1868 db_escape(mysql, host->snmp_sysName, sizeof(host->snmp_sysName), poll_result);
1869 free(poll_result);
1870 }
1871
1872 SPINE_LOG_DEVDBG(("DEVDBG: Device [%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.6.0');", host->id));
1873 poll_result = snmp_get(host, ".1.3.6.1.2.1.1.6.0");
1874 SPINE_LOG_DEVDBG(("DEVDBG: Device [%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.6.0'); [complete]", host->id));
1875
1876 if (poll_result) {
1877 db_escape(mysql, host->snmp_sysLocation, sizeof(host->snmp_sysLocation), poll_result);
1878 free(poll_result);
1879 }
1880 } else {
1881 if (is_debug_device(host->id)) {
1882 SPINE_LOG(("Device[%d] Updating Short System Information Table", host->id));
1883 } else {
1884 SPINE_LOG_MEDIUM(("Device[%d] Updating Short System Information Table", host->id));
1885 }
1886
1887 SPINE_LOG_DEVDBG(("DEVDBG: Device [%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.3.0');", host->id));
1888 poll_result = snmp_get(host, ".1.3.6.1.2.1.1.3.0");
1889 SPINE_LOG_DEVDBG(("DEVDBG: Device [%d] poll_result = snmp_get(host, '.1.3.6.1.2.1.1.3.0'); [complete]", host->id));
1890
1891 if (poll_result) {
1892 host->snmp_sysUpTimeInstance = atoi(poll_result);
1893 free(poll_result);
1894 }
1895 }
1896 }
1897
1898 /*! \fn int validate_result(char *result)
1899 * \brief validates the output from the polling action is valid
1900 * \param result the value to be checked for legality
1901 *
1902 * This function will poll a specific host using the script pointed to by
1903 * the command variable.
1904 *
1905 * \return TRUE if the result is valid, otherwise FALSE.
1906 *
1907 */
validate_result(char * result)1908 int validate_result(char *result) {
1909 /* check the easy cases first */
1910 if (result) {
1911 if (is_numeric(result)) {
1912 return TRUE;
1913 } else {
1914 if (is_multipart_output(trim(result))) {
1915 return TRUE;
1916 } else {
1917 return FALSE;
1918 }
1919 }
1920 }
1921
1922 return FALSE;
1923 }
1924
1925 /*! \fn char *exec_poll(host_t *current_host, char *command, int id, char *type)
1926 * \brief polls a host using a script
1927 * \param current_host a pointer to the current host structure
1928 * \param command the command to be executed
1929 * \param id either the local_data_id or the data_query_id
1930 *
1931 * This function will poll a specific host using the script pointed to by
1932 * the command variable.
1933 *
1934 * \return a pointer to a character buffer containing the result.
1935 *
1936 */
exec_poll(host_t * current_host,char * command,int id,char * type)1937 char *exec_poll(host_t *current_host, char *command, int id, char *type) {
1938 extern sem_t active_scripts;
1939 int cmd_fd;
1940 int pid;
1941 int close_fd = TRUE;
1942
1943 #ifdef USING_TPOPEN
1944 FILE *fd;
1945 #endif
1946
1947 int bytes_read;
1948 fd_set fds;
1949 double begin_time = 0;
1950 double end_time = 0;
1951 double script_timeout;
1952 struct timeval timeout;
1953 char *proc_command;
1954 char *result_string;
1955
1956 /* compensate for back slashes in arguments */
1957 #if defined(__CYGWIN__)
1958 proc_command = add_slashes(command);
1959 #else
1960 proc_command = command;
1961 #endif
1962
1963 if (!(result_string = (char *) malloc(RESULTS_BUFFER))) {
1964 die("ERROR: Fatal malloc error: poller.c exec_poll!");
1965 }
1966
1967 /* set zeros */
1968 memset(result_string, 0, RESULTS_BUFFER);
1969
1970 /* set script timeout as double */
1971 script_timeout = set.script_timeout;
1972
1973 /* establish timeout of 25 seconds for pipe response */
1974 timeout.tv_sec = set.script_timeout;
1975 timeout.tv_usec = 0;
1976
1977 /* don't run too many scripts, operating systems do not like that. */
1978 sem_wait(&active_scripts);
1979
1980 /* record start time */
1981 begin_time = get_time_as_double();
1982
1983 #ifdef USING_TPOPEN
1984 fd = popen((char *)proc_command, "r");
1985 cmd_fd = fileno(fd);
1986 if (is_debug_device(current_host->id)) {
1987 SPINE_LOG(("DEBUG: Device[%i] DEBUG: The POPEN returned the following File Descriptor %i", current_host->id, cmd_fd));
1988 } else {
1989 SPINE_LOG_DEBUG(("DEBUG: Device[%i] DEBUG: The POPEN returned the following File Descriptor %i", current_host->id, cmd_fd));
1990 }
1991 #else
1992 cmd_fd = nft_popen((char *)proc_command, "r");
1993 if (is_debug_device(current_host->id)) {
1994 SPINE_LOG(("DEBUG: Device[%i] DEBUG: The NIFTY POPEN returned the following File Descriptor %i", current_host->id, cmd_fd));
1995 } else {
1996 SPINE_LOG_DEBUG(("DEBUG: Device[%i] DEBUG: The NIFTY POPEN returned the following File Descriptor %i", current_host->id, cmd_fd));
1997 }
1998 #endif
1999
2000 if (cmd_fd > 0) {
2001 retry:
2002
2003 /* Initialize File Descriptors to Review for Input/Output */
2004 FD_ZERO(&fds);
2005 FD_SET(cmd_fd, &fds);
2006
2007 /* wait x seconds for pipe response */
2008 switch (select(FD_SETSIZE, &fds, NULL, NULL, &timeout)) {
2009 case -1:
2010 switch (errno) {
2011 case EBADF:
2012 SPINE_LOG(("Device[%i] ERROR: One or more of the file descriptor sets specified a file descriptor that is not a valid open file descriptor.", current_host->id));
2013 SET_UNDEFINED(result_string);
2014 close_fd = FALSE;
2015 break;
2016 case EINTR:
2017 #ifndef SOLAR_THREAD
2018 /* take a moment */
2019 usleep(2000);
2020 #endif
2021
2022 /* record end time */
2023 end_time = get_time_as_double();
2024
2025 /* re-establish new timeout value */
2026 timeout.tv_sec = rint(floor(script_timeout-(end_time-begin_time)));
2027 timeout.tv_usec = rint((script_timeout-(end_time-begin_time)-timeout.tv_sec)*1000000);
2028
2029 if ((end_time - begin_time) < set.script_timeout) {
2030 goto retry;
2031 } else {
2032 SPINE_LOG(("WARNING: A script timed out while processing EINTR's."));
2033 SET_UNDEFINED(result_string);
2034 close_fd = FALSE;
2035 }
2036 break;
2037 case EINVAL:
2038 SPINE_LOG(("Device[%i] ERROR: Possible invalid timeout specified in select() statement.", current_host->id));
2039 SET_UNDEFINED(result_string);
2040 close_fd = FALSE;
2041 break;
2042 default:
2043 SPINE_LOG(("Device[%i] ERROR: The script/command select() failed", current_host->id));
2044 SET_UNDEFINED(result_string);
2045 close_fd = FALSE;
2046 break;
2047 }
2048 case 0:
2049 #ifdef USING_TPOPEN
2050 SPINE_LOG_MEDIUM(("Device[%i] ERROR: The POPEN timed out", current_host->id));
2051
2052 close_fd = FALSE;
2053 #else
2054 SPINE_LOG_MEDIUM(("Device[%i] ERROR: The NIFTY POPEN timed out", current_host->id));
2055
2056 pid = nft_pchild(cmd_fd);
2057 kill(pid, SIGKILL);
2058 #endif
2059
2060 SET_UNDEFINED(result_string);
2061 break;
2062 default:
2063 /* get only one line of output, we will ignore the rest */
2064 bytes_read = read(cmd_fd, result_string, RESULTS_BUFFER-1);
2065 if (bytes_read > 0) {
2066 result_string[bytes_read] = '\0';
2067 } else {
2068 if (STRIMATCH(type,"DS")) {
2069 SPINE_LOG(("Device[%i] DS[%i] ERROR: Empty result [%s]: '%s'", current_host->id, id, current_host->hostname, command));
2070 } else {
2071 SPINE_LOG(("Device[%i] DQ[%i] ERROR: Empty result [%s]: '%s'", current_host->id, id, current_host->hostname, command));
2072 }
2073 SET_UNDEFINED(result_string);
2074 }
2075 }
2076
2077 /* close pipe */
2078 #ifdef USING_TPOPEN
2079 /* we leave the old fd open if it timed out. It will have to exit on it's own */
2080 if (close_fd) {
2081 pclose(fd);
2082 }
2083 #else
2084 nft_pclose(cmd_fd);
2085 #endif
2086 } else {
2087 SPINE_LOG(("Device[%i] ERROR: Problem executing POPEN [%s]: '%s'", current_host->id, current_host->hostname, command));
2088 SET_UNDEFINED(result_string);
2089 }
2090
2091 #if defined(__CYGWIN__)
2092 free(proc_command);
2093 #endif
2094
2095 /* reduce the active script count */
2096 sem_post(&active_scripts);
2097
2098 return result_string;
2099 }
2100