/* * check_remote_disk_space.c * 20/01/2006 * Check the percent of avalaible partition space in a remote server using snmp * it works as a nagios plugin too , see the last part of main function * i compile in this way: * # gcc -lnetsnmp -lcrypto -Wall -pedantic thisfile.c -O3 -fomit-frame-pointer -funroll-loops -o check_remote_disk_space * by * Eduardo Ruiz Duarte * erduarte@telmex.com */ #include #if HAVE_STDLIB_H #include #endif #if HAVE_UNISTD_H #include #endif #if HAVE_STRING_H #include #else #include #endif #include #if HAVE_NETINET_IN_H #include #endif #include #include #if TIME_WITH_SYS_TIME #ifdef WIN32 #include #else #include #endif #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #if HAVE_SYS_SELECT_H #include #endif #if HAVE_WINSOCK_H #include #endif #if HAVE_NETDB_H #include #endif #if HAVE_ARPA_INET_H #include #endif #include #include int failures = 0; #define HDESCR "hrStorageDescr.%d" #define HSIZE "hrStorageSize.%d" #define HUSED "hrStorageUsed.%d" #define NETSNMP_DS_APP_DONT_FIX_PDUS 0 int snmp_query_beck (char *community, int version, char *query, char *host, char *buf); void usage (void) { fprintf (stderr, "check_remote_disk_space 0.1 by Eduardo Ruiz Duarte\nerduarte@telmex.com\n"); fprintf (stderr, "-H host (ip or hostname)\n-c community (public,ro_public,etc..)\n-v version (usually 1,2c or 3)\n-p partition (/export/home,c:)\n"); fprintf (stderr, "Optional flags are:\n-l (to dump all the partition descriptions)\nthe order of the flags has no significance\n"); fprintf (stderr,"Example:\n# check_remote_disk_space -v 2c -p /export/home -c public -H 10.108.132.13 -l\n"); } int main (int argc, char **argv) { char id=0,buf[512], *tptr,*comm=0, *host=0, *partition=0, tmp[sizeof (HDESCR)],*tname; const char *str = "STRING: \0", *inte = "INTEGER: \0"; unsigned int version=0, i, vflag, cflag, hflag, pflag, lflag, total_size=0,used_size=0; float percent; if (argc == 1) { usage (); exit (EXIT_FAILURE); } lflag = vflag = cflag = hflag = pflag = 0; for (i = 0; i < argc; i++) { if ((argv[i][0] == '-') && (argv[i][1] == 'v')) { if (argv[i + 1] == NULL) { fprintf (stderr, "-v requires an argument e.g. (1,2c or 3)\n"); exit (EXIT_FAILURE); } if (strcmp (argv[i + 1], "1") == 0) { version = SNMP_VERSION_1; vflag = 1; } if (strcmp (argv[i + 1], "2c") == 0) { version = SNMP_VERSION_2c; vflag = 1; } if (strcmp (argv[i + 1], "3") == 0) { version = SNMP_VERSION_3; vflag = 1; } else if (vflag != 1) { fprintf (stderr, "Version \'%s\' unknown , it has to be \'1\',\'2c\' or \'3\'\n", argv[i + 1]); usage (); exit (EXIT_FAILURE); } } if ((argv[i][0] == '-') && (argv[i][1] == 'c')) { if (argv[i + 1] == NULL) { fprintf (stderr, "-c requires an argument e.g. \'public\'\n"); usage (); exit (EXIT_FAILURE); } comm = argv[i + 1]; cflag = 1; } if ((argv[i][0] == '-') && (argv[i][1] == 'l')) lflag = 1; if ((argv[i][0] == '-') && (argv[i][1] == 'H')) { if (argv[i + 1] == NULL) { fprintf (stderr, "-H requires an argument e.g. \'192.168.1.2\'\n"); usage (); exit (EXIT_FAILURE); } host = argv[i + 1]; hflag = 1; } if ((argv[i][0] == '-') && (argv[i][1] == 'p')) { if (argv[i + 1] == NULL) { fprintf (stderr, "-p requires an argument e.g. \'/export/home or C:\'\n"); usage (); exit (EXIT_FAILURE); } partition = argv[i + 1]; pflag = 1; } if ((argv[i][0] == '-') && (argv[i][1] == 'h')) { usage (); exit (EXIT_FAILURE); } } if (cflag == 0) { fprintf (stderr, "You need to specify a community with option -c\n"); exit (EXIT_FAILURE); } if (vflag == 0) { fprintf (stderr, "You need to specify the version of th snmp protocol tu use with -v\n"); exit (EXIT_FAILURE); } if (pflag == 0) { fprintf (stderr, "You need to specify a partition to check avalaible space with -p\n"); exit (EXIT_FAILURE); } if (hflag == 0) { usage(); exit (EXIT_FAILURE); } memset (&tmp, 0x0, sizeof (HDESCR)); if ((partition[strlen (partition) - 1] == '/') && (strlen(partition) > 1)) partition[strlen (partition) - 1] = 0; if((tptr = strchr(partition,':')) != NULL) partition[0] = tolower(partition[0]); #define MAX_PART 32 for (i = 1; i < MAX_PART; i++) { sprintf ((char *) &tmp, HDESCR, i); memset (&buf, 0x0, sizeof (buf)); if (snmp_query_beck (comm, version, tmp, host,(char *) &buf) != 0) fprintf (stderr, "Error getting %s.. procedding\n", tmp); tname = strstr ((char *) &buf, str); if (tname != NULL) { tname = tname + strlen (str); if((tptr=strchr(tname,':')) != NULL) { tptr[1] = 0; tname[0] = tolower(tname[0]); } if (lflag) printf ("Partition[%d] = %s\n", i, tname); if (strcmp (tname, partition) == 0) { id = i; i = MAX_PART; } } } if (id == 0) { fprintf (stderr, "Partition %s not found in server %s\n", partition, host); exit (EXIT_FAILURE); } memset (&buf, 0x0, sizeof (buf)); sprintf ((char *) &tmp, HSIZE, id); if (snmp_query_beck (comm, version, tmp, host, (char *)&buf) != 0) fprintf (stderr, "Error getting %s.. proceeding\n", tmp); tname = strstr ((char *) &buf, inte); if (tname != NULL) { tname = tname + strlen (inte); total_size = atoi (tname); } memset (&buf, 0x0, sizeof (buf)); sprintf ((char *) &tmp, HUSED, id); if (snmp_query_beck (comm, version, tmp, host,(char *) &buf) != 0) fprintf (stderr, "Error getting %s.. proceeding\n", tmp); tname = strstr ((char *) &buf, inte); if (tname != NULL) { tname = tname + strlen (inte); used_size = atoi (tname); } if (total_size == 0) percent = 0; else percent = (float) ((float) (used_size * 100) / (float) total_size); #define OK 0 #define WARN 1 #define CRIT 2 #define UNK 3 if (percent < 50) { fprintf (stderr,"OK: "); printf ("Mount point: %s avalaible: %.2f%%\n", partition, 100-percent); return OK; } if (percent < 75) { fprintf (stderr,"WARNING: "); printf ("Mount point: %s avalaible: %.2f%%\n", partition, 100-percent); return WARN; } if (percent <= 100) { fprintf (stderr,"CRITICAL: "); printf ("Mount point: %s avalaible: %.2f%%\n", partition, 100-percent); return CRIT; } if(percent < 0 || percent > 100) { fprintf (stderr,"?????: "); printf ("Mount point: %s avalaible: %.2f%%\n", partition, 100-percent); return UNK; } return UNK; } int snmp_query_beck (char *community, int version, char *query, char *host, char *buf) { netsnmp_session session, *ss; netsnmp_pdu *pdu,*response; netsnmp_variable_list *valores; int debug, ret = 0, i; oid name[MAX_OID_LEN]; size_t namelen; snmp_sess_init (&session); session.version = version; session.community = (unsigned char *) community; session.community_len = strlen ((char *) community); init_snmp ("snmpapp"); session.peername = host; SOCK_STARTUP; ss = snmp_open (&session); if (ss == NULL) { snmp_sess_perror ("snmpget", &session); SOCK_CLEANUP; exit (1); } pdu = snmp_pdu_create (SNMP_MSG_GET); namelen = MAX_OID_LEN; if (!snmp_parse_oid ((char *) query, name, &namelen)) { snmp_perror ((char *) query); failures++; } else snmp_add_null_var (pdu, name, namelen); if (failures) { SOCK_CLEANUP; exit (1); } retry: debug = snmp_synch_response (ss, pdu, &response); if (debug == STAT_SUCCESS) { if (response->errstat == SNMP_ERR_NOERROR) { valores = response->variables; snprint_variable (buf, 512, valores->name, valores->name_length, valores); } else { fprintf (stderr, "Error in packet\nReason: %s\n", snmp_errstring (response->errstat)); exit(EXIT_FAILURE); if (response->errindex != 0) { fprintf (stderr, "MIB object failed.. exists ?: "); for (i = 1, valores = response->variables; valores && i != response->errindex; valores = valores->next_variable, i++) if (valores) fprint_objid (stderr, valores->name, valores->name_length); fprintf (stderr, "\n"); } ret = 2; if (!netsnmp_ds_get_boolean (NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_APP_DONT_FIX_PDUS)) { pdu = snmp_fix_pdu (response, SNMP_MSG_GET); snmp_free_pdu (response); response = NULL; if (pdu != NULL) goto retry; } } } else if (debug == STAT_TIMEOUT) { fprintf (stderr, "Timeout: from %s.\n", session.peername); ret = 1; } else { snmp_sess_perror ("snmpget", ss); ret = 1; } if (response) snmp_free_pdu (response); snmp_close (ss); SOCK_CLEANUP; return ret; }