From 4adfa054775c60b1523eb2f69b19773e1dbf899f Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Tue, 11 May 2021 11:08:34 +0200 Subject: [PATCH 01/10] Added match alias only option --- snmp_bulkget.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/snmp_bulkget.c b/snmp_bulkget.c index fd58852..5650f73 100644 --- a/snmp_bulkget.c +++ b/snmp_bulkget.c @@ -126,6 +126,7 @@ main(int argc, char *argv[]) int crit_on_down_flag = 1; int get_aliases_flag = 0; int match_aliases_flag = 0; + int match_aliases_only_flag = 0; int get_names_flag = 0; int print_all_flag = 0; int err_tolerance = 50; @@ -227,6 +228,7 @@ main(int argc, char *argv[]) {"sleep", required_argument, NULL, 3}, {"retries", required_argument, NULL, 4}, {"max-repetitions", required_argument, NULL, 5}, + {"aliases-only", no_argument, NULL, 6}, {NULL, 0, NULL, 0} }; @@ -332,6 +334,10 @@ main(int argc, char *argv[]) case 5: pdu_max_repetitions = strtol(optarg, NULL, 10); break; + case 6: + get_aliases_flag = 1; /* we need to see what we have matched... */ + match_aliases_only_flag = 1; + break; case '?': default: exit(usage(progname)); @@ -610,7 +616,7 @@ main(int argc, char *argv[]) /* now optionally fetch the interface aliases */ - if (match_aliases_flag) { + if (match_aliases_flag || match_aliases_only_flag) { lastifflag = 0; count = 0; /* allocate the space for the alias OIDs */ @@ -888,8 +894,11 @@ main(int argc, char *argv[]) count = 0; for (i=0; i < ifNumber; i++) { + /* When --aliases-only is set check only alias */ + if (match_aliases_only_flag) + status = !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0)); /* When --if-name is set ignore descr in favor of name, else use old behaviour */ - if (get_names_flag) + else if (get_names_flag) status = !regexec(&re, interfaces[i].name, (size_t) 0, NULL, 0) || (get_aliases_flag && !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0))); else @@ -897,9 +906,11 @@ main(int argc, char *argv[]) (get_aliases_flag && !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0))); status2 = 0; if (status && exclude_list) { - if (get_names_flag) + if (match_aliases_only_flag) + status2 = !(regexec(&exclude_re, interfaces[i].alias, (size_t) 0, NULL, 0)); + else if (get_names_flag) status2 = !regexec(&exclude_re, interfaces[i].name, (size_t) 0, NULL, 0) || - (get_aliases_flag && !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0))); + (get_aliases_flag && !(regexec(&exclude_re, interfaces[i].alias, (size_t) 0, NULL, 0))); else status2 = !regexec(&exclude_re, interfaces[i].descr, (size_t) 0, NULL, 0) || (get_aliases_flag && !(regexec(&exclude_re, interfaces[i].alias, (size_t) 0, NULL, 0))); @@ -1353,7 +1364,8 @@ int usage(char *progname) printf(" --timeout\t\tsets the SNMP timeout (in ms)\n"); printf(" --sleep\t\tsleep between every SNMP query (in ms)\n"); printf(" --retries\t\thow often to retry before giving up\n"); - printf(" --max-repetitions\t\tsee \n"); + printf(" --max-repetitions\tsee \n"); + printf(" --aliases-only\tmatch only against aliases (Option -a automatically enabled)\n"); printf("\n"); return 3; } From b9d54c05ccc5a194071b2238bd070cf3b4dbe3b3 Mon Sep 17 00:00:00 2001 From: distahl <46716166+distahl@users.noreply.github.com> Date: Tue, 11 May 2021 11:14:02 +0200 Subject: [PATCH 02/10] --aliases-only option documented --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 46baaf9..52eea6a 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ make install --timeout sets the SNMP timeout (in ms) -m|--mode special operating mode (default,cisco,nonbulk,bintec) Workarounds for various hardware + --aliases-only only test the Alias against the Regexes ### Modes From f216a0cc83df535685ee966650c92733f1520960 Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Tue, 11 May 2021 11:18:45 +0200 Subject: [PATCH 03/10] More information for debugging --- snmp_bulkget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snmp_bulkget.c b/snmp_bulkget.c index 5650f73..f25c8da 100644 --- a/snmp_bulkget.c +++ b/snmp_bulkget.c @@ -917,7 +917,7 @@ main(int argc, char *argv[]) } if (status && !status2) { count++; #ifdef DEBUG - fprintf(stderr, "Interface %d (%s) matched\n", interfaces[i].index, interfaces[i].descr); + fprintf(stderr, "Interface %d - name=\"%s\", desc=\"%s\", alias=\"%s\" - matched\n", interfaces[i].index, interfaces[i].name, interfaces[i].descr, interfaces[i].alias); #endif } else interfaces[i].ignore = 1; From ce38437b92ca919dcb8e80df558cb25aea58334a Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Tue, 11 May 2021 11:19:58 +0200 Subject: [PATCH 04/10] Quick and dirty fix for segfault in debug mode --- snmp_bulkget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snmp_bulkget.c b/snmp_bulkget.c index f25c8da..bf378de 100644 --- a/snmp_bulkget.c +++ b/snmp_bulkget.c @@ -461,7 +461,7 @@ main(int argc, char *argv[]) } #ifdef DEBUG - implode_result = implode(", ", oid_ifp + count); + implode_result = implode(", ", oid_ifp + count + 100); benchmark_start("Send SNMP request for OIDs: %s", implode_result); #endif /* send the request */ @@ -640,7 +640,7 @@ main(int argc, char *argv[]) } #ifdef DEBUG - implode_result = implode(", ", oid_aliasp + count); + implode_result = implode(", ", oid_aliasp + count + 100); benchmark_start("Send SNMP request for OIDs: %s", implode_result); #endif /* send the request */ From 628ca86e9a5fd47b8f3fb6a06b82d4b78fc650bc Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Tue, 11 May 2021 11:21:52 +0200 Subject: [PATCH 05/10] Version 1.5 --- configure | 20 ++++++++++---------- configure.ac | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 04da9c1..f214dc9 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for check_interfaces 1.4. +# Generated by GNU Autoconf 2.69 for check_interfaces 1.5. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='check_interfaces' PACKAGE_TARNAME='check_interfaces' -PACKAGE_VERSION='1.4' -PACKAGE_STRING='check_interfaces 1.4' +PACKAGE_VERSION='1.5' +PACKAGE_STRING='check_interfaces 1.5' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1229,7 +1229,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures check_interfaces 1.4 to adapt to many kinds of systems. +\`configure' configures check_interfaces 1.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1291,7 +1291,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of check_interfaces 1.4:";; + short | recursive ) echo "Configuration of check_interfaces 1.5:";; esac cat <<\_ACEOF @@ -1377,7 +1377,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -check_interfaces configure 1.4 +check_interfaces configure 1.5 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1675,7 +1675,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by check_interfaces $as_me 1.4, which was +It was created by check_interfaces $as_me 1.5, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4138,7 +4138,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by check_interfaces $as_me 1.4, which was +This file was extended by check_interfaces $as_me 1.5, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4191,7 +4191,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -check_interfaces config.status 1.4 +check_interfaces config.status 1.5 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -4312,7 +4312,7 @@ done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.4. +# bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi diff --git a/configure.ac b/configure.ac index 049cfde..2d5dfe8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(check_interfaces, 1.4) +AC_INIT(check_interfaces, 1.5) AC_PREFIX_DEFAULT(/usr/local/nagios) AC_PROG_CC AC_PROG_INSTALL From be1a656c0176fc1417acb7fafad993651b1f74b5 Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Wed, 26 May 2021 13:27:24 +0200 Subject: [PATCH 06/10] Added additional regex targets --- README.md | 72 +++++++++++++++++--------------- snmp_bulkget.c | 110 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 127 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 52eea6a..2081e46 100644 --- a/README.md +++ b/README.md @@ -40,41 +40,45 @@ make install check_interface -c public -h 192.168.0.1 -r 'FastEth' -p '$SERVICEPERFDATA$' -t $LASTSERVICECHECK$ -a Options; - -h address of device - - -c|--community community (default public) - -r|--regex interface list regexp - Regex to match interfaces (important, this is a Regular Expression - not a simple wildcard string, see below) - -e|--errors number of in errors (CRC errors for cisco) to consider a warning (default 50) - Only warn if errors increase by more than this amount between checks - -f|--out-errors number of out errors (collisions for cisco) to consider a warning - Defaults to the same value as for errors - -p|--perfdata last check perfdata - Performance data from previous check (used to calculate traffic) - -P|--prefix prefix interface names with this label - -t|--lastcheck last checktime (unixtime) - Last service check time in unixtime (also used to calculate traffic) - -b|--bandwidth bandwidth warn level in % - -s|--speed override speed detection with this value (bits per sec) - -x|--trim cut this number of characters from the start of interface descriptions - Useful for nortel switches - -j|--auth-proto SNMPv3 Auth Protocol (SHA|MD5) - -J|--auth-phrase SNMPv3 Auth Phrase - -k|--priv-proto SNMPv3 Privacy Protocol (AES|DES) (optional) - -K|--priv-phrase SNMPv3 Privacy Phrase - -u|--user SNMPv3 User - -d|--down-is-ok disables critical alerts for down interfaces - i.e do not consider a down interface to be critical - -a|--aliases retrieves the interface description - This alias does not always deliver useful information - -A|--match-aliases also test the Alias against the Regexes - -D|--debug-print list administrative down interfaces in perfdata - -N|--if-names use ifName instead of ifDescr - --timeout sets the SNMP timeout (in ms) - -m|--mode special operating mode (default,cisco,nonbulk,bintec) + -h address of device + + -c|--community community (default public) + -r|--regex interface list regexp + Regex to match interfaces (important, this is a Regular Expression + not a simple wildcard string, see below) + -e|--errors number of in errors (CRC errors for cisco) to consider a warning (default 50) + Only warn if errors increase by more than this amount between checks + -f|--out-errors number of out errors (collisions for cisco) to consider a warning + Defaults to the same value as for errors + -p|--perfdata last check perfdata + Performance data from previous check (used to calculate traffic) + -P|--prefix prefix interface names with this label + -t|--lastcheck last checktime (unixtime) + Last service check time in unixtime (also used to calculate traffic) + -b|--bandwidth bandwidth warn level in % + -s|--speed override speed detection with this value (bits per sec) + -x|--trim cut this number of characters from the start of interface descriptions + Useful for nortel switches + -j|--auth-proto SNMPv3 Auth Protocol (SHA|MD5) + -J|--auth-phrase SNMPv3 Auth Phrase + -k|--priv-proto SNMPv3 Privacy Protocol (AES|DES) (optional) + -K|--priv-phrase SNMPv3 Privacy Phrase + -u|--user SNMPv3 User + -d|--down-is-ok disables critical alerts for down interfaces + i.e do not consider a down interface to be critical + -a|--aliases retrieves the interface description + This alias does not always deliver useful information + -A|--match-aliases also test the Alias against the Regexes (--regex / --exclude-regex) + -D|--debug-print list administrative down interfaces in perfdata + -N|--if-names use ifName instead of ifDescr + --timeout sets the SNMP timeout (in ms) + -m|--mode special operating mode (default,cisco,nonbulk,bintec) Workarounds for various hardware - --aliases-only only test the Alias against the Regexes + --aliases-only only test the Alias against the Regexes (--regex / --exclude-regex) + --if-regex regexp matching only ifDescr/ifName. Works also with --aliases-only + --if-exclude-regex negative regexp matching only ifDescr/ifName. Works also with --aliases-only + --regex-or match both regexes --regex and --if-regex in an OR operation. So only one of them needs to match. + --exclude-regex-or match both regexes --exclude-regex and --if-exclude-regex in an OR operation. So only one of them needs to match. ### Modes diff --git a/snmp_bulkget.c b/snmp_bulkget.c index bf378de..1032d48 100644 --- a/snmp_bulkget.c +++ b/snmp_bulkget.c @@ -143,6 +143,8 @@ main(int argc, char *argv[]) char *hostname=0, *community=0, *list=0, *oldperfdatap=0, *prefix = 0; char *user = 0, *auth_proto = 0, *auth_pass = 0, *priv_proto = 0, *priv_pass = 0; char *exclude_list = 0; + char *if_list = 0, *if_exclude_list = 0; + int re_or_flag = 0, re_exclude_or_flag = 0; #ifdef INDEXES char *indexes=0; #endif /* INDEXES */ @@ -153,7 +155,7 @@ main(int argc, char *argv[]) struct timeval tv; struct timezone tz; long double starttime; - regex_t re, exclude_re; + regex_t re, exclude_re, if_re, if_exclude_re; int ignore_count = 0; int trimdescr = 0; int opt; @@ -229,6 +231,10 @@ main(int argc, char *argv[]) {"retries", required_argument, NULL, 4}, {"max-repetitions", required_argument, NULL, 5}, {"aliases-only", no_argument, NULL, 6}, + {"if-regex", required_argument, NULL, 7}, + {"if-exclude-regex", required_argument, NULL, 8}, + {"regex-or", no_argument, NULL, 9}, + {"exclude-regex-or", no_argument, NULL, 10}, {NULL, 0, NULL, 0} }; @@ -338,6 +344,18 @@ main(int argc, char *argv[]) get_aliases_flag = 1; /* we need to see what we have matched... */ match_aliases_only_flag = 1; break; + case 7: + if_list = optarg; + break; + case 8: + if_exclude_list = optarg; + break; + case 9: + re_or_flag = 1; + break; + case 10: + re_exclude_or_flag = 1; + break; case '?': default: exit(usage(progname)); @@ -375,6 +393,10 @@ main(int argc, char *argv[]) /* use .* as the default regex */ list = ".*"; + if (if_exclude_list && !if_list) + /* use .* as the default regex */ + if_list = ".*"; + /* get the start time */ gettimeofday(&tv, &tz); starttime=(long double)tv.tv_sec + (((long double)tv.tv_usec)/1000000); @@ -383,14 +405,30 @@ main(int argc, char *argv[]) if (list) { status = regcomp(&re, list, REG_ICASE|REG_EXTENDED|REG_NOSUB); if (status != 0) { - printf("Error creating regex\n"); + printf("Error creating regex (--regex)\n"); exit (3); } if (exclude_list) { status = regcomp(&exclude_re, exclude_list, REG_ICASE|REG_EXTENDED|REG_NOSUB); if (status != 0) { - printf("Error creating exclusion regex\n"); + printf("Error creating exclusion regex (--exclude-regex)\n"); + exit (3); + } + } + } + + if (if_list) { + status = regcomp(&if_re, if_list, REG_ICASE|REG_EXTENDED|REG_NOSUB); + if (status != 0) { + printf("Error creating interface regex (--if-regex)\n"); + exit (3); + } + + if (if_exclude_list) { + status = regcomp(&if_exclude_re, if_exclude_list, REG_ICASE|REG_EXTENDED|REG_NOSUB); + if (status != 0) { + printf("Error creating interface exclusion regex (--if-exclude-regex)\n"); exit (3); } } @@ -884,7 +922,7 @@ main(int argc, char *argv[]) } } - if (list) { + if (list || if_list) { /* * a regex was given so we will go through our array * and try and match it with what we received @@ -894,18 +932,30 @@ main(int argc, char *argv[]) count = 0; for (i=0; i < ifNumber; i++) { - /* When --aliases-only is set check only alias */ - if (match_aliases_only_flag) - status = !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0)); - /* When --if-name is set ignore descr in favor of name, else use old behaviour */ - else if (get_names_flag) - status = !regexec(&re, interfaces[i].name, (size_t) 0, NULL, 0) || - (get_aliases_flag && !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0))); - else - status = !regexec(&re, interfaces[i].descr, (size_t) 0, NULL, 0) || - (get_aliases_flag && !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0))); - status2 = 0; - if (status && exclude_list) { + status = 1; + if (list) { + /* When --aliases-only is set check only alias */ + if (match_aliases_only_flag) + status = !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0)); + /* When --if-name is set ignore descr in favor of name, else use old behaviour */ + else if (get_names_flag) + status = !regexec(&re, interfaces[i].name, (size_t) 0, NULL, 0) || + (get_aliases_flag && !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0))); + else + status = !regexec(&re, interfaces[i].descr, (size_t) 0, NULL, 0) || + (get_aliases_flag && !(regexec(&re, interfaces[i].alias, (size_t) 0, NULL, 0))); + } + + /* Try --if-regex, if needed */ + if (if_list && (!list || (status && !re_or_flag) || (!status && re_or_flag))) { + if (get_names_flag) + status = !regexec(&if_re, interfaces[i].name, (size_t) 0, NULL, 0); + else + status = !regexec(&if_re, interfaces[i].descr, (size_t) 0, NULL, 0); + } + + status2 = 0; + if (status && exclude_list) { if (match_aliases_only_flag) status2 = !(regexec(&exclude_re, interfaces[i].alias, (size_t) 0, NULL, 0)); else if (get_names_flag) @@ -914,7 +964,17 @@ main(int argc, char *argv[]) else status2 = !regexec(&exclude_re, interfaces[i].descr, (size_t) 0, NULL, 0) || (get_aliases_flag && !(regexec(&exclude_re, interfaces[i].alias, (size_t) 0, NULL, 0))); - } if (status && !status2) { + } + + /* Try --if-exclude-regex, if needed */ + if (if_exclude_list && status && (!exclude_list || (!status2 && re_exclude_or_flag) || (status2 && !re_exclude_or_flag))) { + if (get_names_flag) + status2 = !regexec(&if_exclude_re, interfaces[i].name, (size_t) 0, NULL, 0); + else + status2 = !regexec(&if_exclude_re, interfaces[i].descr, (size_t) 0, NULL, 0); + } + + if (status && !status2) { count++; #ifdef DEBUG fprintf(stderr, "Interface %d - name=\"%s\", desc=\"%s\", alias=\"%s\" - matched\n", interfaces[i].index, interfaces[i].name, interfaces[i].descr, interfaces[i].alias); @@ -923,10 +983,14 @@ main(int argc, char *argv[]) interfaces[i].ignore = 1; } regfree(&re); + regfree(&if_re); if (exclude_list) regfree(&exclude_re); + if (if_exclude_list) + regfree(&if_exclude_re); + if (count) { #ifdef DEBUG fprintf(stderr, "- %d interface%s found\n", count, (count==1)?"":"s"); @@ -1091,9 +1155,9 @@ main(int argc, char *argv[]) printf("OK:"); #ifdef DEBUG fprintf(stderr, " %d interfaces found", ifNumber); - if(list) printf(", of which %d matched the regex. ", count); + if(list || if_list) printf(", of which %d matched the regex. ", count); #else - if(list) + if(list || if_list) printf(" %d interface%s found", count, (count==1)?"":"s"); else printf(" %d interface%s found", ifNumber, (ifNumber==1)?"":"s"); @@ -1358,14 +1422,18 @@ int usage(char *progname) printf(" -u|--user\t\tSNMPv3 User\n"); printf(" -d|--down-is-ok\tdisables critical alerts for down interfaces\n"); printf(" -a|--aliases\t\tretrieves the interface description\n"); - printf(" -A|--match-aliases\talso match against aliases (Option -a automatically enabled)\n"); + printf(" -A|--match-aliases\talso match (--regex / --exclude-regex) against aliases (Option -a automatically enabled)\n"); printf(" -D|--debug-print\tlist administrative down interfaces in perfdata\n"); printf(" -N|--if-names\t\tuse ifName instead of ifDescr\n"); printf(" --timeout\t\tsets the SNMP timeout (in ms)\n"); printf(" --sleep\t\tsleep between every SNMP query (in ms)\n"); printf(" --retries\t\thow often to retry before giving up\n"); printf(" --max-repetitions\tsee \n"); - printf(" --aliases-only\tmatch only against aliases (Option -a automatically enabled)\n"); + printf(" --aliases-only\tmatch (--regex / --exclude-regex) only against aliases (Option -a automatically enabled)\n"); + printf(" --if-regex\t\tregexp matching only ifDescr/ifName (works also with --aliases-only)\n"); + printf(" --if-exclude-regex\tnegative regexp matching only ifDescr/ifName (works also with --aliases-only)\n"); + printf(" --regex-or\t\tmatch both regexes --regex and --if-regex in an OR operation. So only one of them needs to match.\n"); + printf(" --exclude-regex-or\tmatch both regexes --exclude-regex and --if-exclude-regex in an OR operation. So only one of them needs to match.\n"); printf("\n"); return 3; } From 803f84486da54a2fe730b8bbb5b5714c7f7fa905 Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Thu, 27 May 2021 15:42:18 +0200 Subject: [PATCH 07/10] Fix for segfault with wrong interface count --- snmp_bulkget.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/snmp_bulkget.c b/snmp_bulkget.c index 1032d48..2a431cc 100644 --- a/snmp_bulkget.c +++ b/snmp_bulkget.c @@ -541,8 +541,20 @@ main(int argc, char *argv[]) vars = vars->next_variable; } - interfaces = (struct ifStruct*)calloc((size_t)ifNumber, sizeof(struct ifStruct)); - oldperfdata = (struct ifStruct*)calloc((size_t)ifNumber, sizeof(struct ifStruct)); + /* SNMP request result for ifNumber is not always reliable working. + Sometimes it reports a wrong amount, which can lead to segfaults + (not enough memory allocated for varaibles interfaces/oldperfdata). + That's why we should count the real amount of interface entries. */ + int ifCount = 0; + netsnmp_variable_list *tmpvars; + for (tmpvars = vars; tmpvars; tmpvars = tmpvars->next_variable) { + if (tmpvars->type == ASN_OCTET_STR) ifCount++; + if ((tmpvars->name_length < OIDp[2].name_len) || (memcmp(OIDp[2].name, tmpvars->name, (tmpvars->name_length - 1) * sizeof(oid)))) break; + } + ifCount = (ifCount > ifNumber) ? ifCount : ifNumber; + + interfaces = (struct ifStruct*)calloc((size_t)ifCount, sizeof(struct ifStruct)); + oldperfdata = (struct ifStruct*)calloc((size_t)ifCount, sizeof(struct ifStruct)); #ifdef DEBUG fprintf(stderr, "got %d interfaces\n", ifNumber); @@ -589,7 +601,7 @@ main(int argc, char *argv[]) } } - if (count < ifNumber) { + if (count != ifNumber) { if (lastifflag) { #ifdef DEBUG From e19fa3159998389cbb5da21f1e0eb78a123df74a Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Thu, 27 May 2021 16:25:22 +0200 Subject: [PATCH 08/10] Reverted ce38437 & implemted a better solution for segfault in debug mode --- .gitignore | 3 +++ snmp_bulkget.c | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f68911e..864e9b0 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,6 @@ m4/lt~obsolete.m4 # http://www.gnu.org/software/make/ /Makefile + +# Binary +/check_interfaces diff --git a/snmp_bulkget.c b/snmp_bulkget.c index 2a431cc..ca9b148 100644 --- a/snmp_bulkget.c +++ b/snmp_bulkget.c @@ -119,6 +119,7 @@ main(int argc, char *argv[]) netsnmp_variable_list *vars; int status, status2; int count = 0; /* used for: the number of interfaces we receive, the number of regex matches */ + int loopCount = 0; int i, j, k; int errorflag = 0; int warnflag = 0; @@ -499,7 +500,7 @@ main(int argc, char *argv[]) } #ifdef DEBUG - implode_result = implode(", ", oid_ifp + count + 100); + implode_result = implode(", ", oid_ifp + loopCount); benchmark_start("Send SNMP request for OIDs: %s", implode_result); #endif /* send the request */ @@ -655,6 +656,8 @@ main(int argc, char *argv[]) snmp_free_pdu(response); response = 0; } + + loopCount++; } if (OIDp) { @@ -669,6 +672,7 @@ main(int argc, char *argv[]) if (match_aliases_flag || match_aliases_only_flag) { lastifflag = 0; count = 0; + loopCount = 0; /* allocate the space for the alias OIDs */ OIDp = (struct OIDStruct *) calloc(1, sizeof(struct OIDStruct)); while (lastifflag==0) { @@ -690,7 +694,7 @@ main(int argc, char *argv[]) } #ifdef DEBUG - implode_result = implode(", ", oid_aliasp + count + 100); + implode_result = implode(", ", oid_aliasp + loopCount); benchmark_start("Send SNMP request for OIDs: %s", implode_result); #endif /* send the request */ @@ -774,6 +778,8 @@ main(int argc, char *argv[]) response = 0; } + loopCount++; + } } From 43f7b07618d516ec73592ad20f02af03667186cc Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Fri, 28 May 2021 08:47:51 +0200 Subject: [PATCH 09/10] Bugfix for 803f844 --- snmp_bulkget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snmp_bulkget.c b/snmp_bulkget.c index ca9b148..c05d9f2 100644 --- a/snmp_bulkget.c +++ b/snmp_bulkget.c @@ -602,7 +602,7 @@ main(int argc, char *argv[]) } } - if (count != ifNumber) { + if (count < ifNumber) { if (lastifflag) { #ifdef DEBUG From df2ce9358e48e05a82fe29c154c9b97cd935189b Mon Sep 17 00:00:00 2001 From: dstahlbe Date: Fri, 28 May 2021 14:37:07 +0200 Subject: [PATCH 10/10] Rework/Bugfix of 803f844 (interface count). Missed the fact, that there can be more than one snmp request. --- snmp_bulkget.c | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/snmp_bulkget.c b/snmp_bulkget.c index c05d9f2..f9576d7 100644 --- a/snmp_bulkget.c +++ b/snmp_bulkget.c @@ -85,6 +85,7 @@ void create_pdu(int, char **, netsnmp_pdu **, struct OIDStruct **, int, long); +void* realloc_zero(void*, size_t, size_t); /* hardware mode */ @@ -96,7 +97,7 @@ unsigned int lastcheck = 0; unsigned long global_timeout = DFLT_TIMEOUT; static -int ifNumber = 0; +int ifNumber = 0, ifCount = 0; #ifdef DEBUG static @@ -116,7 +117,7 @@ main(int argc, char *argv[]) netsnmp_pdu *pdu; netsnmp_pdu *response; - netsnmp_variable_list *vars; + netsnmp_variable_list *vars, *vars2; int status, status2; int count = 0; /* used for: the number of interfaces we receive, the number of regex matches */ int loopCount = 0; @@ -542,20 +543,8 @@ main(int argc, char *argv[]) vars = vars->next_variable; } - /* SNMP request result for ifNumber is not always reliable working. - Sometimes it reports a wrong amount, which can lead to segfaults - (not enough memory allocated for varaibles interfaces/oldperfdata). - That's why we should count the real amount of interface entries. */ - int ifCount = 0; - netsnmp_variable_list *tmpvars; - for (tmpvars = vars; tmpvars; tmpvars = tmpvars->next_variable) { - if (tmpvars->type == ASN_OCTET_STR) ifCount++; - if ((tmpvars->name_length < OIDp[2].name_len) || (memcmp(OIDp[2].name, tmpvars->name, (tmpvars->name_length - 1) * sizeof(oid)))) break; - } - ifCount = (ifCount > ifNumber) ? ifCount : ifNumber; - - interfaces = (struct ifStruct*)calloc((size_t)ifCount, sizeof(struct ifStruct)); - oldperfdata = (struct ifStruct*)calloc((size_t)ifCount, sizeof(struct ifStruct)); + interfaces = (struct ifStruct*)calloc((size_t)ifNumber, sizeof(struct ifStruct)); + oldperfdata = (struct ifStruct*)calloc((size_t)ifNumber, sizeof(struct ifStruct)); #ifdef DEBUG fprintf(stderr, "got %d interfaces\n", ifNumber); @@ -564,6 +553,25 @@ main(int argc, char *argv[]) /* subsequent replies have no ifNumber */ } + /* SNMP request result for ifNumber is not always reliable working. + Sometimes it reports a wrong amount, which can lead to segfaults + (not enough memory allocated for varaibles interfaces/oldperfdata). + That's why we should count the real amount of interface entries. */ + for (vars2 = vars; vars2; vars2 = vars2->next_variable) { + if ((vars2->name_length < OIDp[2].name_len) || (memcmp(OIDp[2].name, vars2->name, (vars2->name_length - 1) * sizeof(oid)))) break; + if (vars2->type == ASN_OCTET_STR) ifCount++; + } + + if (ifCount > ifNumber) { + size_t newSize = (size_t)((ifCount + ifNumber) * sizeof(struct ifStruct)); + size_t oldSize = (size_t)(ifNumber * sizeof(struct ifStruct)); + interfaces = realloc_zero(interfaces, oldSize, newSize); + oldperfdata = realloc_zero(oldperfdata, oldSize, newSize); +#ifdef DEBUG + fprintf(stderr, "got %d additional interfaces\n", (ifCount - ifNumber)); +#endif + ifNumber = ifCount; + } for (vars = vars; vars; vars = vars->next_variable) { /* @@ -1687,3 +1695,13 @@ void create_pdu(int mode, char **oidlist, netsnmp_pdu **pdu, struct OIDStruct ** snmp_add_null_var(*pdu, (*oids)[i].name, (*oids)[i].name_len); } } + +void* realloc_zero(void* pBuffer, size_t oldSize, size_t newSize) { + void* pNew = realloc(pBuffer, newSize); + if ( newSize > oldSize && pNew ) { + size_t diff = newSize - oldSize; + void* pStart = ((char*)pNew) + oldSize; + memset(pStart, 0, diff); + } + return pNew; +}