hostres_fs_tbl.c revision 160341
1154133Sharti/*- 2154133Sharti * Copyright (c) 2005-2006 The FreeBSD Project 3154133Sharti * All rights reserved. 4154133Sharti * 5154133Sharti * Author: Victor Cruceru <soc-victor@freebsd.org> 6154133Sharti * 7154133Sharti * Redistribution of this software and documentation and use in source and 8154133Sharti * binary forms, with or without modification, are permitted provided that 9154133Sharti * the following conditions are met: 10154133Sharti * 11154133Sharti * 1. Redistributions of source code or documentation must retain the above 12154133Sharti * copyright notice, this list of conditions and the following disclaimer. 13154133Sharti * 2. Redistributions in binary form must reproduce the above copyright 14154133Sharti * notice, this list of conditions and the following disclaimer in the 15154133Sharti * documentation and/or other materials provided with the distribution. 16154133Sharti * 17154133Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18154133Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19154133Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20154133Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21154133Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22154133Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23154133Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24154133Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25154133Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26154133Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27154133Sharti * SUCH DAMAGE. 28154133Sharti * 29154133Sharti * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_fs_tbl.c 160341 2006-07-14 09:07:56Z harti $ 30154133Sharti */ 31154133Sharti 32154133Sharti/* 33154133Sharti * Host Resources MIB for SNMPd. Implementation for hrFSTable 34154133Sharti */ 35154133Sharti 36154133Sharti#include <sys/types.h> 37154133Sharti#include <sys/param.h> 38154133Sharti#include <sys/sysctl.h> 39154133Sharti#include <sys/mount.h> 40154133Sharti 41154133Sharti#include <assert.h> 42154133Sharti#include <err.h> 43154133Sharti#include <stdlib.h> 44154133Sharti#include <string.h> 45154133Sharti#include <syslog.h> 46160341Sharti#include <sysexits.h> 47154133Sharti 48154133Sharti#include "hostres_snmp.h" 49154133Sharti#include "hostres_oid.h" 50154133Sharti#include "hostres_tree.h" 51154133Sharti 52154133Sharti/* 53154133Sharti * File system access enum 54154133Sharti */ 55154133Shartienum hrFSAccess { 56154133Sharti FS_READ_WRITE = 1, 57154133Sharti FS_READ_ONLY = 2 58154133Sharti}; 59154133Sharti 60160341Sharti/* maximum length (according to MIB) for fs_entry::mountPoint */ 61160341Sharti#define FS_MP_MLEN (128 + 1) 62160341Sharti 63160341Sharti/* maximum length (according to MIB) for fs_entry::remoteMountPoint */ 64160341Sharti#define FS_RMP_MLEN (128 + 1) 65160341Sharti 66154133Sharti/* 67154133Sharti * This structure is used to hold a SNMP table entry 68154133Sharti * for HOST-RESOURCES-MIB's hrFSTable 69154133Sharti */ 70154133Shartistruct fs_entry { 71154133Sharti int32_t index; 72160341Sharti u_char *mountPoint; 73160341Sharti u_char *remoteMountPoint; 74154133Sharti const struct asn_oid *type; 75154133Sharti int32_t access; /* enum hrFSAccess, see above */ 76154133Sharti int32_t bootable; /* TruthValue */ 77154133Sharti int32_t storageIndex; /* hrStorageTblEntry::index */ 78154133Sharti u_char lastFullBackupDate[11]; 79154133Sharti u_char lastPartialBackupDate[11]; 80160341Sharti#define HR_FS_FOUND 0x001 81154133Sharti uint32_t flags; /* not in mib table, for internal use */ 82154133Sharti TAILQ_ENTRY(fs_entry) link; 83154133Sharti}; 84154133ShartiTAILQ_HEAD(fs_tbl, fs_entry); 85154133Sharti 86154133Sharti/* 87154133Sharti * Next structure is used to keep o list of mappings from a specific name 88154133Sharti * (a_name) to an entry in the hrFSTblEntry. We are trying to keep the same 89154133Sharti * index for a specific name at least for the duration of one SNMP agent run. 90154133Sharti */ 91154133Shartistruct fs_map_entry { 92160341Sharti int32_t hrIndex; /* used for fs_entry::index */ 93160341Sharti u_char *a_name; /* map key same as fs_entry::mountPoint */ 94154133Sharti 95154133Sharti /* may be NULL if the respective hrFSTblEntry is (temporally) gone */ 96154133Sharti struct fs_entry *entry; 97154133Sharti STAILQ_ENTRY(fs_map_entry) link; 98154133Sharti}; 99154133ShartiSTAILQ_HEAD(fs_map, fs_map_entry); 100154133Sharti 101154133Sharti/* head of the list with hrFSTable's entries */ 102154133Shartistatic struct fs_tbl fs_tbl = TAILQ_HEAD_INITIALIZER(fs_tbl); 103154133Sharti 104154133Sharti/* for consistent table indexing */ 105154133Shartistatic struct fs_map fs_map = STAILQ_HEAD_INITIALIZER(fs_map); 106154133Sharti 107154133Sharti/* next index available for hrFSTable */ 108154133Shartistatic uint32_t next_fs_index = 1; 109154133Sharti 110154133Sharti/* last tick when hrFSTable was updated */ 111154133Shartistatic uint64_t fs_tick; 112154133Sharti 113154133Sharti/* maximum number of ticks between refreshs */ 114154133Shartiuint32_t fs_tbl_refresh = HR_FS_TBL_REFRESH * 100; 115154133Sharti 116154133Sharti/* some constants */ 117154133Shartistatic const struct asn_oid OIDX_hrFSBerkeleyFFS_c = OIDX_hrFSBerkeleyFFS; 118154133Shartistatic const struct asn_oid OIDX_hrFSiso9660_c = OIDX_hrFSiso9660; 119154133Shartistatic const struct asn_oid OIDX_hrFSNFS_c = OIDX_hrFSNFS; 120154133Shartistatic const struct asn_oid OIDX_hrFSLinuxExt2_c = OIDX_hrFSLinuxExt2; 121154133Shartistatic const struct asn_oid OIDX_hrFSOther_c = OIDX_hrFSOther; 122154133Shartistatic const struct asn_oid OIDX_hrFSFAT32_c = OIDX_hrFSFAT32; 123154133Shartistatic const struct asn_oid OIDX_hrFSNTFS_c = OIDX_hrFSNTFS; 124154133Shartistatic const struct asn_oid OIDX_hrFSNetware_c = OIDX_hrFSNetware; 125154133Shartistatic const struct asn_oid OIDX_hrFSHPFS_c = OIDX_hrFSHPFS; 126154133Shartistatic const struct asn_oid OIDX_hrFSUnknown_c = OIDX_hrFSUnknown; 127154133Sharti 128154133Sharti/* file system type map */ 129154133Shartistatic const struct { 130154133Sharti const char *str; /* the type string */ 131154133Sharti const struct asn_oid *oid; /* the OID to return */ 132154133Sharti} fs_type_map[] = { 133154133Sharti { "ufs", &OIDX_hrFSBerkeleyFFS_c }, 134154133Sharti { "cd9660", &OIDX_hrFSiso9660_c }, 135154133Sharti { "nfs", &OIDX_hrFSNFS_c }, 136154133Sharti { "ext2fs", &OIDX_hrFSLinuxExt2_c }, 137154133Sharti { "procfs", &OIDX_hrFSOther_c }, 138154133Sharti { "devfs", &OIDX_hrFSOther_c }, 139154133Sharti { "msdosfs", &OIDX_hrFSFAT32_c }, 140154133Sharti { "ntfs", &OIDX_hrFSNTFS_c }, 141154133Sharti { "nwfs", &OIDX_hrFSNetware_c }, 142154133Sharti { "hpfs", &OIDX_hrFSHPFS_c }, 143154133Sharti { "smbfs", &OIDX_hrFSOther_c }, 144154133Sharti}; 145154133Sharti#define N_FS_TYPE_MAP (sizeof(fs_type_map) / sizeof(fs_type_map[0])) 146154133Sharti 147154133Sharti/** 148154133Sharti * Create an entry into the FS table and an entry in the map (if needed). 149154133Sharti */ 150154133Shartistatic struct fs_entry * 151154133Shartifs_entry_create(const char *name) 152154133Sharti{ 153154133Sharti struct fs_entry *entry; 154154133Sharti struct fs_map_entry *map; 155154133Sharti 156160341Sharti assert(name != NULL); 157160341Sharti assert(strlen(name) > 0); 158154133Sharti 159154133Sharti STAILQ_FOREACH(map, &fs_map, link) 160160341Sharti if (strcmp(map->a_name, name) == 0) 161154133Sharti break; 162154133Sharti 163154133Sharti if (map == NULL) { 164160341Sharti size_t mount_point_len; 165160341Sharti 166154133Sharti /* new object - get a new index */ 167154133Sharti if (next_fs_index > INT_MAX) { 168160341Sharti /* Unrecoverable error - die clean and quicly*/ 169154133Sharti syslog(LOG_ERR, "%s: hrFSTable index wrap", __func__); 170160341Sharti errx(EX_SOFTWARE, "hrFSTable index wrap"); 171154133Sharti } 172154133Sharti 173154133Sharti if ((map = malloc(sizeof(*map))) == NULL) { 174154133Sharti syslog(LOG_ERR, "%s: %m", __func__); 175154133Sharti return (NULL); 176154133Sharti } 177154133Sharti 178160341Sharti mount_point_len = strlen(name) + 1; 179160341Sharti if (mount_point_len > FS_MP_MLEN) 180160341Sharti mount_point_len = FS_MP_MLEN; 181160341Sharti 182160341Sharti if ((map->a_name = malloc(mount_point_len)) == NULL) { 183160341Sharti syslog(LOG_ERR, "%s: %m", __func__); 184160341Sharti free(map); 185160341Sharti return (NULL); 186160341Sharti } 187160341Sharti 188160341Sharti strlcpy(map->a_name, name, mount_point_len); 189160341Sharti 190154133Sharti map->hrIndex = next_fs_index++; 191160341Sharti map->entry = NULL; 192154133Sharti STAILQ_INSERT_TAIL(&fs_map, map, link); 193154133Sharti 194154133Sharti HRDBG("%s added into hrFSMap at index=%d", name, map->hrIndex); 195154133Sharti } else { 196154133Sharti HRDBG("%s exists in hrFSMap index=%d", name, map->hrIndex); 197154133Sharti } 198154133Sharti 199160341Sharti if ((entry = malloc(sizeof(*entry))) == NULL) { 200160341Sharti syslog(LOG_WARNING, "%s: %m", __func__); 201160341Sharti return (NULL); 202160341Sharti } 203160341Sharti 204160341Sharti if ((entry->mountPoint = strdup(name)) == NULL) { 205160341Sharti syslog(LOG_ERR, "%s: %m", __func__); 206160341Sharti free(entry); 207160341Sharti return (NULL); 208160341Sharti } 209160341Sharti 210154133Sharti entry->index = map->hrIndex; 211160341Sharti map->entry = entry; 212154133Sharti 213154133Sharti INSERT_OBJECT_INT(entry, &fs_tbl); 214154133Sharti return (entry); 215154133Sharti} 216154133Sharti 217154133Sharti/** 218154133Sharti * Delete an entry in the FS table. 219154133Sharti */ 220154133Shartistatic void 221154133Shartifs_entry_delete(struct fs_entry* entry) 222154133Sharti{ 223154133Sharti struct fs_map_entry *map; 224154133Sharti 225160341Sharti assert(entry != NULL); 226160341Sharti 227154133Sharti TAILQ_REMOVE(&fs_tbl, entry, link); 228154133Sharti STAILQ_FOREACH(map, &fs_map, link) 229154133Sharti if (map->entry == entry) { 230154133Sharti map->entry = NULL; 231154133Sharti break; 232154133Sharti } 233160341Sharti free(entry->mountPoint); 234160341Sharti free(entry->remoteMountPoint); 235154133Sharti free(entry); 236154133Sharti} 237154133Sharti 238154133Sharti/** 239154133Sharti * Find a table entry by its name 240154133Sharti */ 241154133Shartistatic struct fs_entry * 242154133Shartifs_find_by_name(const char *name) 243154133Sharti{ 244154133Sharti struct fs_entry *entry; 245154133Sharti 246154133Sharti TAILQ_FOREACH(entry, &fs_tbl, link) 247160341Sharti if (strcmp(entry->mountPoint, name) == 0) 248154133Sharti return (entry); 249154133Sharti 250154133Sharti return (NULL); 251154133Sharti} 252154133Sharti 253154133Sharti/** 254154133Sharti * Get rid of all data 255154133Sharti */ 256154133Shartivoid 257154133Shartifini_fs_tbl(void) 258154133Sharti{ 259154133Sharti struct fs_map_entry *n1; 260154133Sharti 261154133Sharti while ((n1 = STAILQ_FIRST(&fs_map)) != NULL) { 262154133Sharti STAILQ_REMOVE_HEAD(&fs_map, link); 263154133Sharti if (n1->entry != NULL) { 264154133Sharti TAILQ_REMOVE(&fs_tbl, n1->entry, link); 265160341Sharti free(n1->entry->mountPoint); 266160341Sharti free(n1->entry->remoteMountPoint); 267154133Sharti free(n1->entry); 268154133Sharti } 269160341Sharti free(n1->a_name); 270154133Sharti free(n1); 271154133Sharti } 272154133Sharti assert(TAILQ_EMPTY(&fs_tbl)); 273154133Sharti} 274154133Sharti 275154133Sharti/** 276154133Sharti * Called before the refreshing is started from the storage table. 277154133Sharti */ 278154133Shartivoid 279154133Shartifs_tbl_pre_refresh(void) 280154133Sharti{ 281154133Sharti struct fs_entry *entry; 282154133Sharti 283154133Sharti /* mark each entry as missisng */ 284154133Sharti TAILQ_FOREACH(entry, &fs_tbl, link) 285154133Sharti entry->flags &= ~HR_FS_FOUND; 286154133Sharti} 287154133Sharti 288154133Sharti/** 289154133Sharti * Called after refreshing from the storage table. 290154133Sharti */ 291154133Shartivoid 292154133Shartifs_tbl_post_refresh(void) 293154133Sharti{ 294154133Sharti struct fs_entry *entry, *entry_tmp; 295154133Sharti 296154133Sharti /* 297154133Sharti * Purge items that disappeared 298154133Sharti */ 299154133Sharti TAILQ_FOREACH_SAFE(entry, &fs_tbl, link, entry_tmp) 300154133Sharti if (!(entry->flags & HR_FS_FOUND)) 301154133Sharti fs_entry_delete(entry); 302154133Sharti 303154133Sharti fs_tick = this_tick; 304154133Sharti} 305154133Sharti 306154133Sharti/* 307154133Sharti * Refresh the FS table. This is done by forcing a refresh of the storage table. 308154133Sharti */ 309154133Shartivoid 310154133Shartirefresh_fs_tbl(void) 311154133Sharti{ 312154133Sharti 313154133Sharti if (fs_tick == 0 || this_tick - fs_tick >= fs_tbl_refresh) { 314154133Sharti refresh_storage_tbl(1); 315154133Sharti HRDBG("refresh DONE"); 316154133Sharti } 317154133Sharti} 318154133Sharti 319154133Sharti/** 320154133Sharti * Get the type OID for a given file system 321154133Sharti */ 322154133Sharticonst struct asn_oid * 323154133Shartifs_get_type(const struct statfs *fs_p) 324154133Sharti{ 325154133Sharti u_int t; 326154133Sharti 327154133Sharti assert(fs_p != NULL); 328154133Sharti 329154133Sharti for (t = 0; t < N_FS_TYPE_MAP; t++) 330154133Sharti if (strcmp(fs_type_map[t].str, fs_p->f_fstypename) == 0) 331154133Sharti return (fs_type_map[t].oid); 332154133Sharti 333154133Sharti return (&OIDX_hrFSUnknown_c); 334154133Sharti} 335154133Sharti 336154133Sharti/* 337154133Sharti * Given information returned from statfs(2) either create a new entry into 338154133Sharti * the fs_tbl or refresh the entry if it is already there. 339154133Sharti */ 340154133Shartivoid 341154133Shartifs_tbl_process_statfs_entry(const struct statfs *fs_p, int32_t storage_idx) 342154133Sharti{ 343154133Sharti struct fs_entry *entry; 344154133Sharti 345154133Sharti assert(fs_p != 0); 346154133Sharti 347154133Sharti HRDBG("for hrStorageEntry::index %d", storage_idx); 348154133Sharti 349154133Sharti if (fs_p == NULL) 350154133Sharti return; 351154133Sharti 352154133Sharti if ((entry = fs_find_by_name(fs_p->f_mntonname)) != NULL || 353154133Sharti (entry = fs_entry_create(fs_p->f_mntonname)) != NULL) { 354154133Sharti entry->flags |= HR_FS_FOUND; 355154133Sharti 356160341Sharti if (!(fs_p->f_flags & MNT_LOCAL)) { 357154133Sharti /* this is a remote mount */ 358160341Sharti entry->remoteMountPoint = strdup(fs_p->f_mntfromname); 359160341Sharti /* if strdup failed, let it be NULL */ 360154133Sharti 361160341Sharti } else { 362160341Sharti entry->remoteMountPoint = strdup(""); 363160341Sharti /* if strdup failed, let it be NULL */ 364160341Sharti } 365160341Sharti 366154133Sharti entry->type = fs_get_type(fs_p); 367154133Sharti 368154133Sharti if ((fs_p->f_flags & MNT_RDONLY) == MNT_RDONLY) 369154133Sharti entry->access = FS_READ_ONLY; 370154133Sharti else 371154133Sharti entry->access = FS_READ_WRITE; 372154133Sharti 373154133Sharti /* FIXME - bootable fs ?! */ 374154133Sharti entry->bootable = TRUTH_MK((fs_p->f_flags & MNT_ROOTFS) 375154133Sharti == MNT_ROOTFS); 376154133Sharti 377154133Sharti entry->storageIndex = storage_idx; 378154133Sharti 379154133Sharti /* Info not available */ 380154133Sharti memset(entry->lastFullBackupDate, 0, 381154133Sharti sizeof(entry->lastFullBackupDate)); 382154133Sharti 383154133Sharti /* Info not available */ 384154133Sharti memset(entry->lastPartialBackupDate, 0, 385154133Sharti sizeof(entry->lastPartialBackupDate)); 386154133Sharti 387154133Sharti handle_partition_fs_index(fs_p->f_mntfromname, entry->index); 388154133Sharti } 389154133Sharti} 390154133Sharti 391154133Sharti/* 392154133Sharti * This is the implementation for a generated (by our SNMP "compiler" tool) 393154133Sharti * function prototype, see hostres_tree.h 394154133Sharti * It handles the SNMP operations for hrFSTable 395154133Sharti */ 396154133Shartiint 397154133Shartiop_hrFSTable(struct snmp_context *ctx __unused, struct snmp_value *value, 398154133Sharti u_int sub, u_int iidx __unused, enum snmp_op curr_op) 399154133Sharti{ 400154133Sharti struct fs_entry *entry; 401154133Sharti 402154133Sharti refresh_fs_tbl(); 403154133Sharti 404154133Sharti switch (curr_op) { 405154133Sharti 406154133Sharti case SNMP_OP_GETNEXT: 407154133Sharti if ((entry = NEXT_OBJECT_INT(&fs_tbl, 408154133Sharti &value->var, sub)) == NULL) 409154133Sharti return (SNMP_ERR_NOSUCHNAME); 410154133Sharti value->var.len = sub + 1; 411154133Sharti value->var.subs[sub] = entry->index; 412154133Sharti goto get; 413154133Sharti 414154133Sharti case SNMP_OP_GET: 415154133Sharti if ((entry = FIND_OBJECT_INT(&fs_tbl, 416154133Sharti &value->var, sub)) == NULL) 417154133Sharti return (SNMP_ERR_NOSUCHNAME); 418154133Sharti goto get; 419154133Sharti 420154133Sharti case SNMP_OP_SET: 421154133Sharti if ((entry = FIND_OBJECT_INT(&fs_tbl, 422154133Sharti &value->var, sub)) == NULL) 423154133Sharti return (SNMP_ERR_NO_CREATION); 424154133Sharti return (SNMP_ERR_NOT_WRITEABLE); 425154133Sharti 426154133Sharti case SNMP_OP_ROLLBACK: 427154133Sharti case SNMP_OP_COMMIT: 428154133Sharti abort(); 429154133Sharti } 430154133Sharti abort(); 431154133Sharti get: 432154133Sharti switch (value->var.subs[sub - 1]) { 433154133Sharti 434154133Sharti case LEAF_hrFSIndex: 435154133Sharti value->v.integer = entry->index; 436154133Sharti return (SNMP_ERR_NOERROR); 437154133Sharti 438154133Sharti case LEAF_hrFSMountPoint: 439154133Sharti return (string_get(value, entry->mountPoint, -1)); 440154133Sharti 441154133Sharti case LEAF_hrFSRemoteMountPoint: 442160341Sharti if (entry->remoteMountPoint == NULL) 443160341Sharti return (string_get(value, "", -1)); 444160341Sharti else 445160341Sharti return (string_get(value, entry->remoteMountPoint, -1)); 446154133Sharti break; 447154133Sharti 448154133Sharti case LEAF_hrFSType: 449160341Sharti assert(entry->type != NULL); 450160341Sharti value->v.oid = *(entry->type); 451154133Sharti return (SNMP_ERR_NOERROR); 452154133Sharti 453154133Sharti case LEAF_hrFSAccess: 454154133Sharti value->v.integer = entry->access; 455154133Sharti return (SNMP_ERR_NOERROR); 456154133Sharti 457154133Sharti case LEAF_hrFSBootable: 458154133Sharti value->v.integer = entry->bootable; 459154133Sharti return (SNMP_ERR_NOERROR); 460154133Sharti 461154133Sharti case LEAF_hrFSStorageIndex: 462154133Sharti value->v.integer = entry->storageIndex; 463154133Sharti return (SNMP_ERR_NOERROR); 464154133Sharti 465154133Sharti case LEAF_hrFSLastFullBackupDate: 466154133Sharti return (string_get(value, entry->lastFullBackupDate, 8)); 467154133Sharti 468154133Sharti case LEAF_hrFSLastPartialBackupDate: 469154133Sharti return (string_get(value, entry->lastPartialBackupDate, 8)); 470154133Sharti } 471154133Sharti abort(); 472154133Sharti} 473