| /* |
| * disk.c |
| */ |
| |
| #include <config.h> |
| |
| #include <stdio.h> |
| |
| #if HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #if HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| #if HAVE_FCNTL_H |
| #include <fcntl.h> |
| #endif |
| #include <signal.h> |
| #if HAVE_MACHINE_PARAM_H |
| #include <machine/param.h> |
| #endif |
| #if HAVE_SYS_VMMETER_H |
| #if !(defined(bsdi2) || defined(netbsd1)) |
| #include <sys/vmmeter.h> |
| #endif |
| #endif |
| #if HAVE_SYS_CONF_H |
| #include <sys/conf.h> |
| #endif |
| #if HAVE_SYS_PARAM_H |
| #include <sys/param.h> |
| #endif |
| #if HAVE_ASM_PAGE_H |
| #include <asm/page.h> |
| #endif |
| #if HAVE_SYS_SWAP_H |
| #include <sys/swap.h> |
| #endif |
| #if HAVE_SYS_FS_H |
| #include <sys/fs.h> |
| #else |
| #if HAVE_UFS_FS_H |
| #include <ufs/fs.h> |
| #else |
| #ifdef HAVE_SYS_STAT_H |
| #include <sys/stat.h> |
| #endif |
| #ifdef HAVE_SYS_VNODE_H |
| #include <sys/vnode.h> |
| #endif |
| #ifdef HAVE_UFS_UFS_QUOTA_H |
| #include <ufs/ufs/quota.h> |
| #endif |
| #ifdef HAVE_UFS_UFS_INODE_H |
| #include <ufs/ufs/inode.h> |
| #endif |
| #if HAVE_UFS_FFS_FS_H |
| #include <ufs/ffs/fs.h> |
| #endif |
| #endif |
| #endif |
| #if HAVE_MTAB_H |
| #include <mtab.h> |
| #endif |
| #include <sys/stat.h> |
| #include <errno.h> |
| #if HAVE_SYS_STATFS_H |
| #include <sys/statfs.h> |
| #endif |
| #if HAVE_SYS_STATVFS_H |
| #include <sys/statvfs.h> |
| #endif |
| #if HAVE_SYS_VFS_H |
| #include <sys/vfs.h> |
| #endif |
| #if (!defined(HAVE_STATVFS)) && defined(HAVE_STATFS) |
| #if HAVE_SYS_MOUNT_H |
| #include <sys/mount.h> |
| #endif |
| #if HAVE_SYS_SYSCTL_H |
| #include <sys/sysctl.h> |
| #endif |
| #define statvfs statfs |
| #endif |
| #if HAVE_VM_VM_H |
| #include <vm/vm.h> |
| #endif |
| #if HAVE_VM_SWAP_PAGER_H |
| #include <vm/swap_pager.h> |
| #endif |
| #if HAVE_SYS_FIXPOINT_H |
| #include <sys/fixpoint.h> |
| #endif |
| #if HAVE_MALLOC_H |
| #include <malloc.h> |
| #endif |
| #if HAVE_STRING_H |
| #include <string.h> |
| #endif |
| #if HAVE_FSTAB_H |
| #include <fstab.h> |
| #endif |
| #if HAVE_MNTENT_H |
| #include <mntent.h> |
| #endif |
| #if HAVE_SYS_MNTTAB_H |
| #include <sys/mnttab.h> |
| #endif |
| #if HAVE_NETINET_IN_H |
| #include <netinet/in.h> |
| #endif |
| #if TIME_WITH_SYS_TIME |
| # ifdef WIN32 |
| # include <sys/timeb.h> |
| # else |
| # include <sys/time.h> |
| # endif |
| # include <time.h> |
| #else |
| # if HAVE_SYS_TIME_H |
| # include <sys/time.h> |
| # else |
| # include <time.h> |
| # endif |
| #endif |
| #if HAVE_WINSOCK_H |
| #include <winsock.h> |
| #endif |
| |
| #if HAVE_DMALLOC_H |
| #include <dmalloc.h> |
| #endif |
| |
| #include "mibincl.h" |
| #include "struct.h" |
| #include "disk.h" |
| #include "util_funcs.h" |
| #include "read_config.h" |
| #include "agent_read_config.h" |
| #include "mib_module_config.h" |
| #include "auto_nlist.h" |
| #if USING_UCD_SNMP_ERRORMIB_MODULE |
| #include "errormib.h" |
| #else |
| #define setPerrorstatus(x) snmp_log_perror(x) |
| #endif |
| #include "system.h" |
| |
| int numdisks; |
| struct diskpart disks[MAXDISKS]; |
| |
| struct variable2 extensible_disk_variables[] = { |
| {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_disk, 1, {MIBINDEX}}, |
| {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_disk, 1, {ERRORNAME}}, |
| {DISKDEVICE, ASN_OCTET_STR, RONLY, var_extensible_disk, 1, {DISKDEVICE}}, |
| {DISKMINIMUM, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKMINIMUM}}, |
| {DISKMINPERCENT, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKMINPERCENT}}, |
| {DISKTOTAL, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKTOTAL}}, |
| {DISKAVAIL, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKAVAIL}}, |
| {DISKUSED, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKUSED}}, |
| {DISKPERCENT, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKPERCENT}}, |
| {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_disk, 1, {ERRORFLAG }}, |
| {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_disk, 1, {ERRORMSG }} |
| }; |
| |
| /* Define the OID pointer to the top of the mib tree that we're |
| registering underneath */ |
| oid disk_variables_oid[] = { EXTENSIBLEMIB,DISKMIBNUM,1 }; |
| |
| void init_disk(void) |
| { |
| /* register ourselves with the agent to handle our mib tree */ |
| REGISTER_MIB("ucd-snmp/disk", extensible_disk_variables, variable2, \ |
| disk_variables_oid); |
| |
| snmpd_register_config_handler("disk", disk_parse_config, disk_free_config, |
| "path [ minspace | minpercent% ]"); |
| } |
| |
| void disk_free_config (void) |
| { |
| int i; |
| |
| numdisks = 0; |
| for(i=0;i<MAXDISKS;i++) { /* init/erase disk db */ |
| disks[i].device[0] = 0; |
| disks[i].path[0] = 0; |
| disks[i].minimumspace = -1; |
| disks[i].minpercent = -1; |
| } |
| } |
| |
| void disk_parse_config(char *token, char *cptr) |
| { |
| #if HAVE_GETMNTENT |
| #if HAVE_SYS_MNTTAB_H |
| struct mnttab mnttab; |
| #else |
| struct mntent *mntent; |
| #endif |
| FILE *mntfp; |
| #else |
| #if HAVE_FSTAB_H |
| struct fstab *fstab; |
| struct stat stat1; |
| #endif |
| #endif |
| char tmpbuf[1024]; |
| #if defined(HAVE_GETMNTENT) && !defined(HAVE_SETMNTENT) |
| int i; |
| #endif |
| |
| #if HAVE_FSTAB_H || HAVE_GETMNTENT |
| if (numdisks == MAXDISKS) { |
| config_perror("Too many disks specified."); |
| sprintf(tmpbuf,"\tignoring: %s",cptr); |
| config_perror(tmpbuf); |
| } |
| else { |
| /* read disk path (eg, /1 or /usr) */ |
| copy_word(cptr,disks[numdisks].path); |
| cptr = skip_not_white(cptr); |
| cptr = skip_white(cptr); |
| /* read optional minimum disk usage spec */ |
| if (cptr != NULL) { |
| if (strchr(cptr, '%') == 0) { |
| disks[numdisks].minimumspace = atoi(cptr); |
| disks[numdisks].minpercent = -1; |
| } |
| else { |
| disks[numdisks].minimumspace = -1; |
| disks[numdisks].minpercent = atoi(cptr); |
| } |
| } |
| else { |
| disks[numdisks].minimumspace = DEFDISKMINIMUMSPACE; |
| disks[numdisks].minpercent = -1; |
| } |
| /* find the device associated with the directory */ |
| #if HAVE_GETMNTENT |
| #if HAVE_SETMNTENT |
| mntfp = setmntent(ETC_MNTTAB, "r"); |
| disks[numdisks].device[0] = 0; |
| while ((mntent = getmntent (mntfp))) |
| if (strcmp (disks[numdisks].path, mntent->mnt_dir) == 0) { |
| copy_word (mntent->mnt_fsname, disks[numdisks].device); |
| DEBUGMSGTL(("ucd-snmp/disk", "Disk: %s\n",mntent->mnt_fsname)); |
| break; |
| } |
| else { |
| DEBUGMSGTL(("ucd-snmp/disk", " %s != %s\n", disks[numdisks].path, |
| mntent->mnt_dir)); |
| } |
| endmntent(mntfp); |
| if (disks[numdisks].device[0] != 0) { |
| /* dummy clause for else below */ |
| numdisks += 1; /* but inc numdisks here after test */ |
| } |
| #else /* getmentent but not setmntent */ |
| mntfp = fopen (ETC_MNTTAB, "r"); |
| while ((i = getmntent (mntfp, &mnttab)) == 0) |
| if (strcmp (disks[numdisks].path, mnttab.mnt_mountp) == 0) |
| break; |
| else { |
| DEBUGMSGTL(("ucd-snmp/disk", " %s != %s\n", disks[numdisks].path, mnttab.mnt_mountp)); |
| } |
| fclose (mntfp); |
| if (i == 0) { |
| copy_word (mnttab.mnt_special, disks[numdisks].device); |
| numdisks += 1; |
| } |
| #endif /* HAVE_SETMNTENT */ |
| #else |
| #if HAVE_FSTAB_H |
| stat(disks[numdisks].path,&stat1); |
| setfsent(); |
| if ((fstab = getfsfile(disks[numdisks].path))) { |
| copy_word(fstab->fs_spec,disks[numdisks].device); |
| numdisks += 1; |
| } |
| #endif |
| #endif |
| else { |
| sprintf(tmpbuf, "Couldn't find device for disk %s", |
| disks[numdisks].path); |
| config_pwarn(tmpbuf); |
| disks[numdisks].minimumspace = -1; |
| disks[numdisks].minpercent = -1; |
| disks[numdisks].path[0] = 0; |
| } |
| #if HAVE_FSTAB_H |
| endfsent(); |
| #endif |
| } |
| #else |
| config_perror("'disk' checks not supported on this architecture."); |
| #endif |
| } |
| /* |
| var_extensible_disk(... |
| Arguments: |
| vp IN - pointer to variable entry that points here |
| name IN/OUT - IN/name requested, OUT/name found |
| length IN/OUT - length of IN/OUT oid's |
| exact IN - TRUE if an exact match was requested |
| var_len OUT - length of variable or 0 if function returned |
| write_method |
| |
| */ |
| |
| u_char *var_extensible_disk(struct variable *vp, |
| oid *name, |
| size_t *length, |
| int exact, |
| size_t *var_len, |
| WriteMethod **write_method) |
| { |
| |
| int percent, iserror, disknum=0; |
| #if !defined(HAVE_SYS_STATVFS_H) && !defined(HAVE_STATFS) |
| double totalblks, free, used, avail, availblks; |
| #else |
| static long avail; |
| #endif |
| static long long_ret; |
| static char errmsg[300]; |
| |
| #if defined(HAVE_STATVFS) || defined(HAVE_STATFS) |
| #ifdef STAT_STATFS_FS_DATA |
| struct fs_data fsd; |
| struct { |
| u_int f_blocks, f_bfree, f_bavail; |
| } vfs; |
| #else |
| struct statvfs vfs; |
| #endif |
| #else |
| #if HAVE_FSTAB_H |
| int file; |
| union { |
| struct fs iu_fs; |
| char dummy[SBSIZE]; |
| } sb; |
| #define filesys sb.iu_fs |
| #endif |
| #endif |
| |
| if (header_simple_table(vp,name,length,exact,var_len,write_method,numdisks)) |
| return(NULL); |
| disknum = name[*length - 1] - 1; |
| switch (vp->magic) { |
| case MIBINDEX: |
| long_ret = disknum+1; |
| return((u_char *) (&long_ret)); |
| case ERRORNAME: /* DISKPATH */ |
| *var_len = strlen(disks[disknum].path); |
| return((u_char *) disks[disknum].path); |
| case DISKDEVICE: |
| *var_len = strlen(disks[disknum].device); |
| return((u_char *) disks[disknum].device); |
| case DISKMINIMUM: |
| long_ret = disks[disknum].minimumspace; |
| return((u_char *) (&long_ret)); |
| case DISKMINPERCENT: |
| long_ret = disks[disknum].minpercent; |
| return((u_char *) (&long_ret)); |
| } |
| #if defined(HAVE_SYS_STATVFS_H) || defined(HAVE_STATFS) |
| #ifdef STAT_STATFS_FS_DATA |
| if (statvfs (disks[disknum].path, &fsd) == -1) { |
| #else |
| if (statvfs (disks[disknum].path, &vfs) == -1) { |
| #endif |
| snmp_log(LOG_ERR,"Couldn't open device %s\n",disks[disknum].device); |
| setPerrorstatus("statvfs dev/disk"); |
| return NULL; |
| } |
| #ifdef STAT_STATFS_FS_DATA |
| vfs.f_blocks = fsd.fd_btot; |
| vfs.f_bfree = fsd.fd_bfree; |
| vfs.f_bavail = fsd.fd_bfreen; |
| #endif |
| #if defined(HAVE_ODS) |
| vfs.f_blocks = vfs.f_spare[0]; |
| vfs.f_bfree = vfs.f_spare[1]; |
| vfs.f_bavail = vfs.f_spare[2]; |
| #endif |
| percent = vfs.f_bavail <= 0 ? 100 : |
| (int) ((double) (vfs.f_blocks - vfs.f_bfree) / |
| (double) (vfs.f_blocks - (vfs.f_bfree - vfs.f_bavail)) * 100.0 + 0.5); |
| avail = vfs.f_bavail; |
| #ifdef STRUCT_STATVFS_HAS_F_FRSIZE |
| if (vfs.f_frsize > 255) |
| avail = avail * (vfs.f_frsize / 1024); |
| #endif |
| iserror = (disks[disknum].minimumspace >= 0 ? |
| avail < disks[disknum].minimumspace : |
| 100-percent <= disks[disknum].minpercent) ? 1 : 0; |
| switch (vp->magic) { |
| case DISKTOTAL: |
| long_ret = vfs.f_blocks; |
| #ifdef STRUCT_STATVFS_HAS_F_FRSIZE |
| if (vfs.f_frsize > 255) |
| long_ret = long_ret * (vfs.f_frsize / 1024); |
| #endif |
| return((u_char *) (&long_ret)); |
| case DISKAVAIL: |
| return((u_char *) (&avail)); |
| case DISKUSED: |
| long_ret = (vfs.f_blocks - vfs.f_bfree); |
| #ifdef STRUCT_STATVFS_HAS_F_FRSIZE |
| if (vfs.f_frsize > 255) |
| long_ret = long_ret * (vfs.f_frsize / 1024); |
| #endif |
| return((u_char *) (&long_ret)); |
| case DISKPERCENT: |
| long_ret = percent; |
| return ((u_char *) (&long_ret)); |
| case ERRORFLAG: |
| long_ret = iserror; |
| return((u_char *) (&long_ret)); |
| case ERRORMSG: |
| if (iserror) |
| { |
| if (disks[disknum].minimumspace >= 0) |
| sprintf(errmsg,"%s: less than %d free (= %d)",disks[disknum].path, |
| disks[disknum].minimumspace, (int) avail); |
| else |
| sprintf(errmsg,"%s: less than %d%% free (= %d%%)",disks[disknum].path, |
| disks[disknum].minpercent, percent); |
| } |
| else |
| errmsg[0] = 0; |
| *var_len = strlen(errmsg); |
| return((u_char *) (errmsg)); |
| } |
| #else |
| #if HAVE_FSTAB_H |
| /* read the disk information */ |
| if ((file = open(disks[disknum].device,0)) < 0) { |
| snmp_log(LOG_ERR,"Couldn't open device %s\n",disks[disknum].device); |
| setPerrorstatus("open dev/disk"); |
| return(NULL); |
| } |
| lseek(file, (long) (SBLOCK * DEV_BSIZE), 0); |
| if (read(file,(char *) &filesys, SBSIZE) != SBSIZE) { |
| setPerrorstatus("open dev/disk"); |
| snmp_log(LOG_ERR,"Error reading device %s\n",disks[disknum].device); |
| close(file); |
| return(NULL); |
| } |
| close(file); |
| totalblks = filesys.fs_dsize; |
| free = filesys.fs_cstotal.cs_nbfree * filesys.fs_frag + |
| filesys.fs_cstotal.cs_nffree; |
| used = totalblks - free; |
| availblks = totalblks * (100 - filesys.fs_minfree) / 100; |
| avail = availblks > used ? availblks - used : 0; |
| percent = availblks == 0 ? 100 : (int) ((double) used / (double) totalblks * 100.0 + 0.5); |
| iserror = (disks[disknum].minimumspace >= 0 ? avail * filesys.fs_fsize / 1024 < |
| disks[disknum].minimumspace : 100-percent <= disks[disknum].minpercent) ? 1 : 0; |
| switch (vp->magic) { |
| case DISKTOTAL: |
| long_ret = (totalblks * filesys.fs_fsize / 1024); |
| return((u_char *) (&long_ret)); |
| case DISKAVAIL: |
| long_ret = avail * filesys.fs_fsize/1024; |
| return((u_char *) (&long_ret)); |
| case DISKUSED: |
| long_ret = used * filesys.fs_fsize/1024; |
| return((u_char *) (&long_ret)); |
| case DISKPERCENT: |
| long_ret = percent; |
| return ((u_char *) (&long_ret)); |
| case ERRORFLAG: |
| long_ret = iserror; |
| return((u_char *) (&long_ret)); |
| case ERRORMSG: |
| if (iserror) |
| if (disks[disknum].minimumspace >= 0) |
| sprintf(errmsg,"%s: less than %d free (= %d)",disks[disknum].path, |
| disks[disknum].minimumspace, avail * filesys.fs_fsize/1024); |
| else |
| sprintf(errmsg,"%s: less than %d%% free (= %d%%)",disks[disknum].path, |
| disks[disknum].minpercent, percent); |
| else |
| errmsg[0] = 0; |
| *var_len = strlen(errmsg); |
| return((u_char *) (errmsg)); |
| } |
| #endif |
| #endif |
| return NULL; |
| } |