hostres_scalars.c revision 200953
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_scalars.c 200953 2009-12-24 17:55:47Z ed $ 30154133Sharti */ 31154133Sharti 32154133Sharti/* 33154133Sharti * Host Resources MIB scalars implementation for SNMPd. 34154133Sharti */ 35154133Sharti 36154133Sharti#include <sys/types.h> 37154133Sharti#include <sys/sysctl.h> 38154133Sharti 39154133Sharti#include <pwd.h> 40154133Sharti#include <stdlib.h> 41154133Sharti#include <stdint.h> 42154133Sharti#include <string.h> 43154133Sharti#include <syslog.h> 44200953Sed#define _ULOG_POSIX_NAMES 45200953Sed#include <ulog.h> 46154133Sharti 47154133Sharti#include "hostres_snmp.h" 48154133Sharti#include "hostres_oid.h" 49154133Sharti#include "hostres_tree.h" 50154133Sharti 51154133Sharti/* boot timestamp in centi-seconds */ 52154133Shartistatic uint64_t kernel_boot; 53154133Sharti 54154133Sharti/* physical memory size in Kb */ 55154133Shartistatic uint64_t phys_mem_size; 56154133Sharti 57154133Sharti/* boot line (malloced) */ 58154133Shartistatic u_char *boot_line; 59154133Sharti 60154133Sharti/* maximum number of processes */ 61154133Shartistatic uint32_t max_proc; 62154133Sharti 63154133Sharti/** 64154133Sharti * Free all static data 65154133Sharti */ 66154133Shartivoid 67154133Shartifini_scalars(void) 68154133Sharti{ 69154133Sharti 70154133Sharti free(boot_line); 71154133Sharti} 72154133Sharti 73154133Sharti/** 74154133Sharti * Get system uptime in hundredths of seconds since the epoch 75154133Sharti * Returns 0 in case of an error 76154133Sharti */ 77154133Shartistatic int 78154133ShartiOS_getSystemUptime(uint32_t *ut) 79154133Sharti{ 80154133Sharti struct timeval right_now; 81154133Sharti uint64_t now; 82154133Sharti 83154133Sharti if (kernel_boot == 0) { 84154133Sharti /* first time, do the sysctl */ 85154133Sharti struct timeval kernel_boot_timestamp; 86154133Sharti int mib[2] = { CTL_KERN, KERN_BOOTTIME }; 87154133Sharti size_t len = sizeof(kernel_boot_timestamp); 88154133Sharti 89154133Sharti if (sysctl(mib, 2, &kernel_boot_timestamp, 90154133Sharti &len, NULL, 0) == -1) { 91154133Sharti syslog(LOG_ERR, "sysctl KERN_BOOTTIME failed: %m"); 92154133Sharti return (SNMP_ERR_GENERR); 93154133Sharti } 94154133Sharti 95154249Sharti HRDBG("boot timestamp from kernel: {%lld, %ld}", 96154249Sharti (long long)kernel_boot_timestamp.tv_sec, 97154249Sharti (long)kernel_boot_timestamp.tv_usec); 98154133Sharti 99154133Sharti kernel_boot = ((uint64_t)kernel_boot_timestamp.tv_sec * 100) + 100154133Sharti (kernel_boot_timestamp.tv_usec / 10000); 101154133Sharti } 102154133Sharti 103154133Sharti if (gettimeofday(&right_now, NULL) < 0) { 104154133Sharti syslog(LOG_ERR, "gettimeofday failed: %m"); 105154133Sharti return (SNMP_ERR_GENERR); 106154133Sharti } 107154133Sharti now = ((uint64_t)right_now.tv_sec * 100) + (right_now.tv_usec / 10000); 108154133Sharti 109154133Sharti if (now - kernel_boot > UINT32_MAX) 110154133Sharti *ut = UINT32_MAX; 111154133Sharti else 112154133Sharti *ut = now - kernel_boot; 113154133Sharti 114154133Sharti return (SNMP_ERR_NOERROR); 115154133Sharti} 116154133Sharti 117154133Sharti/** 118154133Sharti * Get system local date and time in a foramt suitable for DateAndTime TC: 119154133Sharti * field octets contents range 120154133Sharti * ----- ------ -------- ----- 121154133Sharti * 1 1-2 year* 0..65536 122154133Sharti * 2 3 month 1..12 123154133Sharti * 3 4 day 1..31 124154133Sharti * 4 5 hour 0..23 125154133Sharti * 5 6 minutes 0..59 126154133Sharti * 6 7 seconds 0..60 127154133Sharti * (use 60 for leap-second) 128154133Sharti * 7 8 deci-seconds 0..9 129154133Sharti * 8 9 direction from UTC '+' / '-' 130154133Sharti * 9 10 hours from UTC* 0..13 131154133Sharti * 10 11 minutes from UTC 0..59 132154133Sharti * 133154133Sharti * * Notes: 134154133Sharti * - the value of year is in network-byte order 135154133Sharti * - daylight saving time in New Zealand is +13 136154133Sharti * 137154133Sharti * For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be 138154133Sharti * displayed as: 139154133Sharti * 140154133Sharti * 1992-5-26,13:30:15.0,-4:0 141154133Sharti * 142154133Sharti * Returns -1 in case of an error or the length of the string (8 or 11) 143154133Sharti * Actually returns always 11 on freebsd 144154133Sharti */ 145154133Shartistatic int 146154133ShartiOS_getSystemDate(struct snmp_value *value) 147154133Sharti{ 148154133Sharti u_char s_date_time[11]; 149154133Sharti struct tm tloc_tm; 150154133Sharti time_t tloc_time_t; 151154133Sharti struct timeval right_now; 152154133Sharti int string_len; 153154133Sharti 154154133Sharti if (gettimeofday(&right_now, NULL) < 0) { 155154133Sharti syslog(LOG_ERR, "gettimeofday failed: %m"); 156154133Sharti return (SNMP_ERR_GENERR); 157154133Sharti } 158154133Sharti 159154133Sharti tloc_time_t = right_now.tv_sec; 160154133Sharti 161154133Sharti if (localtime_r(&tloc_time_t, &tloc_tm) == NULL) { 162154133Sharti syslog(LOG_ERR, "localtime_r() failed: %m "); 163154133Sharti return (SNMP_ERR_GENERR); 164154133Sharti } 165154133Sharti 166154133Sharti string_len = make_date_time(s_date_time, &tloc_tm, 167154133Sharti right_now.tv_usec / 100000); 168154133Sharti 169154133Sharti return (string_get(value, s_date_time, string_len)); 170154133Sharti} 171154133Sharti 172154133Sharti/** 173154133Sharti * Get kernel boot path. For FreeBSD it seems that no arguments are 174154133Sharti * present. Returns NULL if an error occured. The returned data is a 175154133Sharti * pointer to a global strorage. 176154133Sharti */ 177154133Shartiint 178154133ShartiOS_getSystemInitialLoadParameters(u_char **params) 179154133Sharti{ 180154133Sharti 181154133Sharti if (boot_line == NULL) { 182154133Sharti int mib[2] = { CTL_KERN, KERN_BOOTFILE }; 183154133Sharti char *buf; 184154133Sharti size_t buf_len = 0; 185154133Sharti 186154133Sharti /* get the needed buffer len */ 187154133Sharti if (sysctl(mib, 2, NULL, &buf_len, NULL, 0) != 0) { 188154133Sharti syslog(LOG_ERR, 189154133Sharti "sysctl({CTL_KERN,KERN_BOOTFILE}) failed: %m"); 190154133Sharti return (SNMP_ERR_GENERR); 191154133Sharti } 192154133Sharti 193154133Sharti if ((buf = malloc(buf_len)) == NULL) { 194154133Sharti syslog(LOG_ERR, "malloc failed"); 195154133Sharti return (SNMP_ERR_GENERR); 196154133Sharti } 197154133Sharti if (sysctl(mib, 2, buf, &buf_len, NULL, 0)) { 198154133Sharti syslog(LOG_ERR, 199154133Sharti "sysctl({CTL_KERN,KERN_BOOTFILE}) failed: %m"); 200154133Sharti free(buf); 201154133Sharti return (SNMP_ERR_GENERR); 202154133Sharti } 203154133Sharti 204154133Sharti boot_line = buf; 205154133Sharti HRDBG("kernel boot file: %s", boot_line); 206154133Sharti } 207154133Sharti 208154133Sharti *params = boot_line; 209154133Sharti return (SNMP_ERR_NOERROR); 210154133Sharti} 211154133Sharti 212154133Sharti/** 213154133Sharti * Get number of current users which are logged in 214154133Sharti */ 215154133Shartistatic int 216154133ShartiOS_getSystemNumUsers(uint32_t *nu) 217154133Sharti{ 218200953Sed struct utmpx *utmp; 219154133Sharti 220200953Sed setutxent(); 221154133Sharti *nu = 0; 222200953Sed while ((utmp = getutxent()) != NULL) { 223200953Sed if (utmp->ut_type == USER_PROCESS) 224154133Sharti (*nu)++; 225154133Sharti } 226200953Sed endutxent(); 227154133Sharti 228154133Sharti return (SNMP_ERR_NOERROR); 229154133Sharti} 230154133Sharti 231154133Sharti/** 232154133Sharti * Get number of current processes existing into the system 233154133Sharti */ 234154133Shartistatic int 235154133ShartiOS_getSystemProcesses(uint32_t *proc_count) 236154133Sharti{ 237154133Sharti int pc; 238154133Sharti 239154133Sharti if (hr_kd == NULL) 240154133Sharti return (SNMP_ERR_GENERR); 241154133Sharti 242154133Sharti if (kvm_getprocs(hr_kd, KERN_PROC_ALL, 0, &pc) == NULL) { 243154133Sharti syslog(LOG_ERR, "kvm_getprocs failed: %m"); 244154133Sharti return (SNMP_ERR_GENERR); 245154133Sharti } 246154133Sharti 247154133Sharti *proc_count = pc; 248154133Sharti return (SNMP_ERR_NOERROR); 249154133Sharti} 250154133Sharti 251154133Sharti/** 252154133Sharti * Get maximum number of processes allowed on this system 253154133Sharti */ 254154133Shartistatic int 255154133ShartiOS_getSystemMaxProcesses(uint32_t *mproc) 256154133Sharti{ 257154133Sharti 258154133Sharti if (max_proc == 0) { 259154133Sharti int mib[2] = { CTL_KERN, KERN_MAXPROC }; 260154133Sharti int mp; 261154133Sharti size_t len = sizeof(mp); 262154133Sharti 263154133Sharti if (sysctl(mib, 2, &mp, &len, NULL, 0) == -1) { 264154133Sharti syslog(LOG_ERR, "sysctl KERN_MAXPROC failed: %m"); 265154133Sharti return (SNMP_ERR_GENERR); 266154133Sharti } 267154133Sharti max_proc = mp; 268154133Sharti } 269154133Sharti 270154133Sharti *mproc = max_proc; 271154133Sharti return (SNMP_ERR_NOERROR); 272154133Sharti} 273154133Sharti 274154133Sharti/* 275154133Sharti * Get the physical memeory size in Kbytes. 276154133Sharti * Returns SNMP error code. 277154133Sharti */ 278154133Shartistatic int 279154133ShartiOS_getMemorySize(uint32_t *ms) 280154133Sharti{ 281154133Sharti 282154133Sharti if (phys_mem_size == 0) { 283154133Sharti int mib[2] = { CTL_HW, HW_PHYSMEM }; 284154133Sharti u_long physmem; 285154133Sharti size_t len = sizeof(physmem); 286154133Sharti 287154133Sharti if (sysctl(mib, 2, &physmem, &len, NULL, 0) == -1) { 288154133Sharti syslog(LOG_ERR, 289154133Sharti "sysctl({ CTL_HW, HW_PHYSMEM }) failed: %m"); 290154133Sharti return (SNMP_ERR_GENERR); 291154133Sharti } 292154133Sharti 293154133Sharti phys_mem_size = physmem / 1024; 294154133Sharti } 295154133Sharti 296154133Sharti if (phys_mem_size > UINT32_MAX) 297154133Sharti *ms = UINT32_MAX; 298154133Sharti else 299154133Sharti *ms = phys_mem_size; 300154133Sharti return (SNMP_ERR_NOERROR); 301154133Sharti} 302154133Sharti 303154133Sharti/* 304154133Sharti * Try to use the s_date_time parameter as a DateAndTime TC to fill in 305154133Sharti * the second parameter. 306154133Sharti * Returns 0 on succes and -1 for an error. 307154133Sharti * Bug: time zone info is not used 308154133Sharti */ 309154133Shartistatic struct timeval * 310154133ShartiOS_checkSystemDateInput(const u_char *str, u_int len) 311154133Sharti{ 312154133Sharti struct tm tm_to_set; 313154133Sharti time_t t; 314154133Sharti struct timeval *tv; 315154133Sharti 316154133Sharti if (len != 8 && len != 11) 317154133Sharti return (NULL); 318154133Sharti 319154133Sharti if (str[2] == 0 || str[2] > 12 || 320154133Sharti str[3] == 0 || str[3] > 31 || 321154133Sharti str[4] > 23 || str[5] > 59 || str[6] > 60 || str[7] > 9) 322154133Sharti return (NULL); 323154133Sharti 324154133Sharti tm_to_set.tm_year = ((str[0] << 8) + str[1]) - 1900; 325154133Sharti tm_to_set.tm_mon = str[2] - 1; 326154133Sharti tm_to_set.tm_mday = str[3]; 327154133Sharti tm_to_set.tm_hour = str[4]; 328154133Sharti tm_to_set.tm_min = str[5]; 329154133Sharti tm_to_set.tm_sec = str[6]; 330154133Sharti tm_to_set.tm_isdst = 0; 331154133Sharti 332154133Sharti /* now make UTC from it */ 333154133Sharti if ((t = timegm(&tm_to_set)) == (time_t)-1) 334154133Sharti return (NULL); 335154133Sharti 336154133Sharti /* now apply timezone if specified */ 337154133Sharti if (len == 11) { 338154133Sharti if (str[9] > 13 || str[10] > 59) 339154133Sharti return (NULL); 340154133Sharti if (str[8] == '+') 341154133Sharti t += 3600 * str[9] + 60 * str[10]; 342154133Sharti else 343154133Sharti t -= 3600 * str[9] + 60 * str[10]; 344154133Sharti } 345154133Sharti 346154133Sharti if ((tv = malloc(sizeof(*tv))) == NULL) 347154133Sharti return (NULL); 348154133Sharti 349154133Sharti tv->tv_sec = t; 350154133Sharti tv->tv_usec = (int32_t)str[7] * 100000; 351154133Sharti 352154133Sharti return (tv); 353154133Sharti} 354154133Sharti 355154133Sharti/* 356154133Sharti * Set system date and time. Timezone is not changed 357154133Sharti */ 358154133Shartistatic int 359154133ShartiOS_setSystemDate(const struct timeval *timeval_to_set) 360154133Sharti{ 361154133Sharti if (settimeofday(timeval_to_set, NULL) == -1) { 362154133Sharti syslog(LOG_ERR, "settimeofday failed: %m"); 363154133Sharti return (SNMP_ERR_GENERR); 364154133Sharti } 365154133Sharti return (SNMP_ERR_NOERROR); 366154133Sharti} 367154133Sharti 368154133Sharti/* 369154133Sharti * prototype of this function was genrated by gensnmptree tool in header file 370154133Sharti * hostres_tree.h 371154133Sharti * Returns SNMP_ERR_NOERROR on success 372154133Sharti */ 373154133Shartiint 374154133Shartiop_hrSystem(struct snmp_context *ctx, struct snmp_value *value, 375154133Sharti u_int sub, u_int iidx __unused, enum snmp_op curr_op) 376154133Sharti{ 377154133Sharti int err; 378154133Sharti u_char *str; 379154133Sharti 380154133Sharti switch (curr_op) { 381154133Sharti 382154133Sharti case SNMP_OP_GET: 383154133Sharti switch (value->var.subs[sub - 1]) { 384154133Sharti 385154133Sharti case LEAF_hrSystemUptime: 386154133Sharti return (OS_getSystemUptime(&value->v.uint32)); 387154133Sharti 388154133Sharti case LEAF_hrSystemDate: 389154133Sharti return (OS_getSystemDate(value)); 390154133Sharti 391154133Sharti case LEAF_hrSystemInitialLoadDevice: 392154133Sharti value->v.uint32 = 0; /* FIXME */ 393154133Sharti return (SNMP_ERR_NOERROR); 394154133Sharti 395154133Sharti case LEAF_hrSystemInitialLoadParameters: 396154133Sharti if ((err = OS_getSystemInitialLoadParameters(&str)) != 397154133Sharti SNMP_ERR_NOERROR) 398154133Sharti return (err); 399154133Sharti return (string_get(value, str, -1)); 400154133Sharti 401154133Sharti case LEAF_hrSystemNumUsers: 402154133Sharti return (OS_getSystemNumUsers(&value->v.uint32)); 403154133Sharti 404154133Sharti case LEAF_hrSystemProcesses: 405154133Sharti return (OS_getSystemProcesses(&value->v.uint32)); 406154133Sharti 407154133Sharti case LEAF_hrSystemMaxProcesses: 408154133Sharti return (OS_getSystemMaxProcesses(&value->v.uint32)); 409154133Sharti } 410154133Sharti abort(); 411154133Sharti 412154133Sharti case SNMP_OP_SET: 413154133Sharti switch (value->var.subs[sub - 1]) { 414154133Sharti 415154133Sharti case LEAF_hrSystemDate: 416154133Sharti if ((ctx->scratch->ptr1 = 417154133Sharti OS_checkSystemDateInput(value->v.octetstring.octets, 418154133Sharti value->v.octetstring.len)) == NULL) 419154133Sharti return (SNMP_ERR_WRONG_VALUE); 420154133Sharti 421154133Sharti return (SNMP_ERR_NOERROR); 422154133Sharti 423154133Sharti case LEAF_hrSystemInitialLoadDevice: 424154133Sharti case LEAF_hrSystemInitialLoadParameters: 425154133Sharti return (SNMP_ERR_NOT_WRITEABLE); 426154133Sharti 427154133Sharti } 428154133Sharti abort(); 429154133Sharti 430154133Sharti case SNMP_OP_ROLLBACK: 431154133Sharti switch (value->var.subs[sub - 1]) { 432154133Sharti 433154133Sharti case LEAF_hrSystemDate: 434154133Sharti free(ctx->scratch->ptr1); 435154133Sharti return (SNMP_ERR_NOERROR); 436154133Sharti 437154133Sharti case LEAF_hrSystemInitialLoadDevice: 438154133Sharti case LEAF_hrSystemInitialLoadParameters: 439154133Sharti abort(); 440154133Sharti } 441154133Sharti abort(); 442154133Sharti 443154133Sharti case SNMP_OP_COMMIT: 444154133Sharti switch (value->var.subs[sub - 1]) { 445154133Sharti 446154133Sharti case LEAF_hrSystemDate: 447154133Sharti (void)OS_setSystemDate(ctx->scratch->ptr1); 448154133Sharti free(ctx->scratch->ptr1); 449154133Sharti return (SNMP_ERR_NOERROR); 450154133Sharti 451154133Sharti case LEAF_hrSystemInitialLoadDevice: 452154133Sharti case LEAF_hrSystemInitialLoadParameters: 453154133Sharti abort(); 454154133Sharti } 455154133Sharti abort(); 456154133Sharti 457154133Sharti case SNMP_OP_GETNEXT: 458154133Sharti abort(); 459154133Sharti } 460154133Sharti abort(); 461154133Sharti} 462154133Sharti 463154133Sharti/* 464154133Sharti * prototype of this function was genrated by gensnmptree tool 465154133Sharti * in the header file hostres_tree.h 466154133Sharti * Returns SNMP_ERR_NOERROR on success 467154133Sharti */ 468154133Shartiint 469154133Shartiop_hrStorage(struct snmp_context *ctx __unused, struct snmp_value *value, 470154133Sharti u_int sub, u_int iidx __unused, enum snmp_op curr_op) 471154133Sharti{ 472154133Sharti 473154133Sharti /* only GET is possible */ 474154133Sharti switch (curr_op) { 475154133Sharti 476154133Sharti case SNMP_OP_GET: 477154133Sharti switch (value->var.subs[sub - 1]) { 478154133Sharti 479154133Sharti case LEAF_hrMemorySize: 480154133Sharti return (OS_getMemorySize(&value->v.uint32)); 481154133Sharti } 482154133Sharti abort(); 483154133Sharti 484154133Sharti case SNMP_OP_SET: 485154133Sharti return (SNMP_ERR_NOT_WRITEABLE); 486154133Sharti 487154133Sharti case SNMP_OP_ROLLBACK: 488154133Sharti case SNMP_OP_COMMIT: 489154133Sharti case SNMP_OP_GETNEXT: 490154133Sharti abort(); 491154133Sharti } 492154133Sharti abort(); 493154133Sharti} 494