[monitoring-plugins] check_snmp: verify number of responses

Lorenz Kästle git at monitoring-plugins.org
Sun Jul 26 11:10:12 CEST 2026


 Module: monitoring-plugins
 Branch: master
 Commit: e504255038cf5a8847c0e9dec3a2183b3f50ec66
 Author: Lorenz Kästle <lorenz at vulgrim.de>
   Date: Sun Jul 12 16:07:38 2026 +0200
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=e5042550

check_snmp: verify number of responses

check_snmp relied on a SNMP agent to send as many response values
as there were values queried.
This patch adds some safe guards and aborts the execution if
the number of response values is lower than the number of
queries values.

---

 plugins/check_snmp.c                      |  8 +++++++
 plugins/check_snmp.d/check_snmp_helpers.c | 38 ++++++++++++++++---------------
 plugins/check_snmp.d/check_snmp_helpers.h |  1 +
 3 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index b595066a..6615bb63 100644
--- a/plugins/check_snmp.c
+++ b/plugins/check_snmp.c
@@ -302,6 +302,14 @@ int main(int argc, char **argv) {
 		xasprintf(&sc_successfull_query.output, "SNMP query was successful");
 		sc_successfull_query = mp_set_subcheck_state(sc_successfull_query, STATE_OK);
 		mp_add_subcheck_to_check(&overall, sc_successfull_query);
+	} else if (response.number_of_results != config.snmp_params.num_of_test_units) {
+		mp_subcheck sc_strange_query_result = mp_subcheck_init();
+		xasprintf(&sc_strange_query_result.output,
+				  "SNMP query returned %zu results, but %zu were requested",
+				  response.number_of_results, config.snmp_params.num_of_test_units);
+		sc_strange_query_result = mp_set_subcheck_state(sc_strange_query_result, STATE_UNKNOWN);
+		mp_add_subcheck_to_check(&overall, sc_strange_query_result);
+		mp_exit(overall);
 	} else {
 		// Error treatment here, either partial or whole
 		mp_subcheck sc_failed_query = mp_subcheck_init();
diff --git a/plugins/check_snmp.d/check_snmp_helpers.c b/plugins/check_snmp.d/check_snmp_helpers.c
index c266edeb..0b188289 100644
--- a/plugins/check_snmp.d/check_snmp_helpers.c
+++ b/plugins/check_snmp.d/check_snmp_helpers.c
@@ -204,6 +204,7 @@ snmp_responces do_snmp_query(check_snmp_config_snmp_parameters parameters) {
 	snmp_responces result = {
 		.errorcode = OK,
 		.response_values = calloc(parameters.num_of_test_units, sizeof(response_value)),
+		.number_of_results = 0,
 	};
 
 	if (result.response_values == NULL) {
@@ -212,19 +213,19 @@ snmp_responces do_snmp_query(check_snmp_config_snmp_parameters parameters) {
 	}
 
 	// We got the the query results, now process them
-	size_t loop_index = 0;
 	for (netsnmp_variable_list *vars = response->variables;
-		 (vars && loop_index <= parameters.num_of_test_units);
-		 vars = vars->next_variable, loop_index++) {
+		 (vars && result.number_of_results <= parameters.num_of_test_units);
+		 vars = vars->next_variable, result.number_of_results++) {
 		for (size_t jdx = 0; jdx < vars->name_length; jdx++) {
-			result.response_values[loop_index].oid[jdx] = vars->name[jdx];
+			result.response_values[result.number_of_results].oid[jdx] = vars->name[jdx];
 		}
-		result.response_values[loop_index].oid_length = vars->name_length;
+		result.response_values[result.number_of_results].oid_length = vars->name_length;
 
 		switch (vars->type) {
 		case ASN_OCTET_STR: {
-			result.response_values[loop_index].string_response = strdup((char *)vars->val.string);
-			result.response_values[loop_index].type = vars->type;
+			result.response_values[result.number_of_results].string_response =
+				strdup((char *)vars->val.string);
+			result.response_values[result.number_of_results].type = vars->type;
 			if (verbose) {
 				printf("Debug: Got a string as response: %s\n", vars->val.string);
 			}
@@ -242,8 +243,8 @@ snmp_responces do_snmp_query(check_snmp_config_snmp_parameters parameters) {
 			}
 			struct counter64 tmp = *(vars->val.counter64);
 			uint64_t counter = (tmp.high << 32) + tmp.low;
-			result.response_values[loop_index].value.uIntVal = counter;
-			result.response_values[loop_index].type = vars->type;
+			result.response_values[result.number_of_results].value.uIntVal = counter;
+			result.response_values[result.number_of_results].type = vars->type;
 		} break;
 		case ASN_GAUGE: // same as ASN_UNSIGNED
 		case ASN_TIMETICKS:
@@ -252,35 +253,36 @@ snmp_responces do_snmp_query(check_snmp_config_snmp_parameters parameters) {
 			if (verbose) {
 				printf("Debug: Got a Integer like\n");
 			}
-			result.response_values[loop_index].value.uIntVal = (unsigned long)*(vars->val.integer);
-			result.response_values[loop_index].type = vars->type;
+			result.response_values[result.number_of_results].value.uIntVal =
+				(unsigned long)*(vars->val.integer);
+			result.response_values[result.number_of_results].type = vars->type;
 		} break;
 		case ASN_INTEGER: {
 			if (verbose) {
 				printf("Debug: Got a Integer\n");
 			}
-			result.response_values[loop_index].value.intVal = *(vars->val.integer);
-			result.response_values[loop_index].type = vars->type;
+			result.response_values[result.number_of_results].value.intVal = *(vars->val.integer);
+			result.response_values[result.number_of_results].type = vars->type;
 		} break;
 		case ASN_FLOAT: {
 			if (verbose) {
 				printf("Debug: Got a float\n");
 			}
-			result.response_values[loop_index].value.doubleVal = *(vars->val.floatVal);
-			result.response_values[loop_index].type = vars->type;
+			result.response_values[result.number_of_results].value.doubleVal = *(vars->val.floatVal);
+			result.response_values[result.number_of_results].type = vars->type;
 		} break;
 		case ASN_DOUBLE: {
 			if (verbose) {
 				printf("Debug: Got a double\n");
 			}
-			result.response_values[loop_index].value.doubleVal = *(vars->val.doubleVal);
-			result.response_values[loop_index].type = vars->type;
+			result.response_values[result.number_of_results].value.doubleVal = *(vars->val.doubleVal);
+			result.response_values[result.number_of_results].type = vars->type;
 		} break;
 		case ASN_IPADDRESS:
 			if (verbose) {
 				printf("Debug: Got an IP address\n");
 			}
-			result.response_values[loop_index].type = vars->type;
+			result.response_values[result.number_of_results].type = vars->type;
 
 			// TODO: print address here, state always ok? or regex match?
 			break;
diff --git a/plugins/check_snmp.d/check_snmp_helpers.h b/plugins/check_snmp.d/check_snmp_helpers.h
index 95b361ac..f1cec35f 100644
--- a/plugins/check_snmp.d/check_snmp_helpers.h
+++ b/plugins/check_snmp.d/check_snmp_helpers.h
@@ -22,6 +22,7 @@ typedef struct {
 typedef struct {
 	int errorcode;
 	response_value *response_values;
+	size_t number_of_results;
 } snmp_responces;
 snmp_responces do_snmp_query(check_snmp_config_snmp_parameters parameters);
 



More information about the Commits mailing list